Manual:Introduction
FreeCAD is a free, open source parametric 3D modeling application. It is made primarily to model real-world objects, ranging from small electronic components up to large objects such as buildings and civil engineering projects, with a strong focus on 3D-printable objects. FreeCAD is free to download, use, distribute and modify, and its source code is open and published under the very permissive LGPL license. The data you produce with FreeCAD is fully yours, and can be recovered without FreeCAD. FreeCAD is also fundamentally a social project, as it is developed and maintained by a community of developers and users united by their passion for FreeCAD. This manual is an experiment, taking a different approach from the official FreeCAD documentation wiki. The wiki is written collaboratively by dozens of community members. Like most wikis, it contains huge amounts of information but is somewhat difficult to access and navigate by newcomers. This makes it an excellent resource for reference, but a less practical tool for learning FreeCAD. This manual will walk you through much of the information available on the wiki, but we hope the step-by-step approach based on examples and a more unified tone due to a smaller number of authors will make it more suitable for a first contact with FreeCAD. It will become a companion for the wiki, but not replace it. This manual is being written for the newest stable version of FreeCAD, version 0.18 (early 2019). The contents of this manual are published under the Creative Commons 4.0 license, and can be freely used, downloaded, copied, and modified. The source files for this manual are hosted on this wiki, and on the original github account used to write the first version of this book. Easier to read HTML, PDF, MOBI and EPUB versions are available on GitBook. A printed version is being prepared.
FreeCAD is not designed for a particular kind of work, or for making a particular kind of object. Instead, it permits users to produce models of objects of widely differing sizes for many purposes, from small electronic components to 3D-printable pieces all the way up to buildings. Each of these tasks has different dedicated sets of tools and workflows available. FreeCAD is also multiplatform (it runs exactly the same way on Windows, Mac OS and Linux platforms), and it is open source. Being open source, FreeCAD benefits from the contributions and efforts of a large community of programmers, enthusiasts and users worldwide. FreeCAD is essentially an application built by the people who use it, instead of being made by a company trying to sell you a product. It also means that FreeCAD is free, not only to use, but also to distribute, copy, modify, or even sell. FreeCAD benefits from the huge, accumulated experience of the open source world. Internally, it includes several other open source components, and FreeCAD itself can be used as a component in other applications. It possesses many features that have become standard in the open source world, such as supporting a wide range of file formats, and being scriptable, customizable and modifiable. All made possible through a dynamic and enthusiastic community of users. The official website of FreeCAD is at http://www.freecadweb.org
Manual:What is FreeCADThe official FreeCAD download page for Windows and Mac OS is https://github.com/FreeCAD/FreeCAD/releases FreeCAD versions The official releases of FreeCAD, that you can find on the page referenced above and in your distribution's software manager, are stable versions. However, the development of FreeCAD is fast! New features and bug fixes are added almost every single day. Since it is often a long time between stable releases, you might be interested in trying a more bleeding-edge version of FreeCAD. These development versions, or pre-releases, are uploaded from time to time to the download page mentioned above, or, if you are using Ubuntu or Fedora, the FreeCAD community also maintains PPA (Personal Package Archives) and copr 'daily builds' which are regularly updated with the most recent changes. If you are installing FreeCAD in a virtual machine, please be aware that the performance might be poor (in some cases unusable) due to the limits of OpenGL support on most virtual machines.
Manual:InstallingInstalling on Windows
Download an installer (.exe) package corresponding to your version of Windows (32bit or 64bit) from the download page. The FreeCAD installers should work on any windows version starting from Windows 7. Double-click the downloaded installer. Accept the terms of the LGPL license, this will be one of the few cases where you can really, safely click the "accept" button without reading the text. No hidden clauses:You can leave the default path here, or change if you wish:
No need to set the PYTHONPATH variable, unless you plan to do some advanced python programming, in which case you probably already know what this is for:
During the installation, a couple of additional components, which are bundled inside the installer, will be installed too:
That's it, FreeCAD is installed. You will find it in your start menu.
Installing a development version Packaging FreeCAD and creating an installer takes some time and dedication, so usually development (also called pre-release) versions are provided as .zip (or .7z) archives. These don't need to be installed; just unpack them and launch FreeCAD by double-clicking the FreeCAD.exe file that you will find inside. This also allows you to keep both the stable and "unstable" versions together on the same computer.
Uninstalling
Hopefully you won't want to uninstall FreeCAD, but it is good to know how. On Windows and Linux, uninstalling FreeCAD is very straightforward. On Windows, use the standard "remove software" option found in the control panel; on Linux, remove it with the same software manager you used to install it. On Mac OS, simply remove it from the Applications folder.Setting basic preferences
Once FreeCAD is installed, you might want to open it and change some preferences. Preference settings in FreeCAD are located under menu Edit → Preferences. Listed below are some basic settings you may wish to change; you can browse through the preference pages to see if there is anything else you want to change. Language: (General category, General tab) FreeCAD will automatically pick the language of your operating system, but you might want to change that. FreeCAD is almost fully translated into five or six languages; others are currently only partially translated. You can easily help translating FreeCAD.Auto-load module: (General category, General tab) Normally, FreeCAD will start by showing you the start page. You can skip this and begin a FreeCAD session directly in the workbench of your choice, listed under Startup, Auto load module after startup. Workbenches will be explained in detail in the next chapter. Create new document at startup: (General category, Document tab) Combined with the Auto-load module option above, if checked this starts FreeCAD ready for work.
Storage options: (General category, Document tab) As with any complex application, FreeCAD likely contains bugs causing it to crash occasionally. Here you can configure options to help you to recover your work in case of a crash. Authoring and license: (General category, Document tab) Here you set the values to be used for new files you create. Consider making your files shareable right from the start, by using a friendlier, copyleft license like Creative Commons. Redirect internal python messages: (General category, Output window tab) These two options are always good to check, as they will cause messages from the internal python interpreter to show up in the Report View when there's a problem running a python script.
Units: (General category, Units tab) Here you can set the default units system you wish to use.
Zoom at cursor: (Display category, 3D tab) If set, zoom operations will be focused at the mouse pointer. If unset, the center of the current view is the zoom focus. Invert zoom: (Display category, 3D tab) Inverts the direction of zooming relative to mouse movement.
![]()
Installing additional content
As the FreeCAD project and its community grows quickly, and also because it is easy to extend, external contributions and side-projects made by community members and other enthusiasts begin to appear everywhere on the internet. Most of these external projects are workbenches or macros, and can be easily installed right from within FreeCAD via the Addon Manager located under menu Tools. The addons manager will allow you to install many interesting components, for example: A Parts library, which contains all kinds of useful models, or pieces of models, created by FreeCAD users that can be freely used in your projects. The library can be used and accessed right from inside your FreeCAD installation. Additional workbenches, that extend the functionality of FreeCAD for certain tasks, for example animate parts of your models, or areas, such as sheet metal folding or BIM. Further explanations of each workbench and what tools it contains is given on each addon page, that you can visit by clicking the corresponding link on the addon manager. A collection of macros, which are also available on the FreeCAD wiki along with documentation about how to use them.If you are using the Ubuntu operating system, some of the addons above are also available as packages on the FreeCAD addons PPA Read more More download options FreeCAD PPA for Ubuntu FreeCAD addons PPA for Ubuntu Compile FreeCAD yourself FreeCAD translations FreeCAD github page The FreeCAD addons manager
Manual:The FreeCAD InterfaceThe start center is a convenient "welcome screen", that shows useful information for newcomers, like the latest files you have been working on, what's new in the FreeCAD world, or quick info about the most common Workbenches. It will also notify you if a new stable version of FreeCAD is available. After a while, when you are more familiar with FreeCAD, you may have made changes in the preferences so when FreeCAD starts you find yourself directly in one of the Workbenches with a new document open. Or, simply close the start page tab and create a new document:
![]()
Workbenches
Note that some of the icons have changed between the two screencaptures above. This is where the most important concept used in the FreeCAD interface comes into play: Workbenches. Workbenches are groups of tools (toolbar buttons, menus, and other interface controls) that are grouped together by specialty. Think of a workshop where you have different people working together: A person who works with metal, another with wood. Each of them has, in their workshop, a separate table with specific tools for his/her job. However, they can all work on the same objects. The same happens in FreeCAD. The most important control of the FreeCAD interface is the Workbench selector, which you use to switch from one Workbench to the other:The Workbenches often confuse new users, since it's not always easy to know in which Workbench to look for a specific tool. But they are quick to learn, and after a short while it will feel natural -- realizing it is a convenient way to organize the multitude of tools FreeCAD has to offer. Workbenches are also fully customizable (see below). The same tool may appear in more than one workbench. The button icon for a particular tool will always be the same no matter which workbench it appears in. Later in this manual, you will also find a table showing the contents of all Workbenches.
The interface
Let's have a better look at the different parts of the interface:The 3D view is the main component of the interface; it is where the objects you are working with are drawn and manipulated. You may have several views of the same document (or same objects), or several documents open at the same time. Each of these views may be individually undocked from the main window. You may select objects or parts of objects by clicking them, and you can pan, zoom and rotate the view with the mouse buttons. This will be explained further in the next chapter. In addition to the 3D view panel, the following information panels are available. They may be made visible or hidden by selecting them from View → Panels . The name of the panel appears in the upper left corner of the panel when it is displayed: The combo view has two tabs: The Model tab shows you the contents and structure of your document above and the properties (or parameters) of the selected object(s) below. These properties are separated into two categories: Data (properties which concern the geometry itself) View (properties that affect how the geometry looks on screen). The Tasks tab is where FreeCAD will prompt you for values specific to the workbench and tool you are currently using. For example, entering a 'length' value when the Draft Workbench Line Tool is being used. It will clear and switch back to the Model tab after the OK (or Cancel) button is pressed. Double-clicking the related object in the Model tab will usually reopen the corresponding Task tab in order to modify the settings. The Tasks tab sometimes has puzzling and frustrating side-effects. If the Task tab is not empty, some FreeCAD operations will not work as expected. For example, if you have a single object in your model such as a cube, double-clicking on it will open the Tasks tab to allow you to modify the parameters characterizing the cube. If you have the Selection view open, you will see the cube's internal name listed there. The entire cube will turn green in the 3D panel, indicating the entire cube is selected. Clicking on the background will deselect the entire cube and clear the Selection view. So far, this is normal behavior. However, if you now click on a face of the cube, instead of that face being selected, nothing will be selected — because the Tasks tab has not been completed. Even if you have made no modifications to the parameters there, FreeCAD is waiting for the OK (or other) button in the Tasks tab to be clicked. The report view is normally hidden, but it is a good idea to open it as it will list any information, warnings or errors to help you decipher (or debug) what you may have done wrong. The Python console is also hidden by default. This is where you can interact with the contents of the document using the Python language. Since every action you do on the FreeCAD interface actually executes a piece of Python code, having this open allows you to watch the code unfold in real time — allowing you a wonderful and easy way to learn a little Python on the way, almost without noticing it. The tree view displays only the object tree shown under the Model tab in the combo view. It is normally hidden. The property view displays only the object property information shown at the bottom of the combo view. It is normally hidden. The selection view shows the names of any objects which are currently selected. These are the objects to which a workbench operation will be applied. It can be used to refine the selection by deselecting some of those objects before a workbench operation is applied. The selection view can also be used to search for objects by name and then select them. By default, the selection view is hidden. While you can often determine the currently selected object(s) by looking at the object tree in the Model tab of the combo view, for complex operations requiring multiple selections and where selection is difficult it is helpful to make this view visible so you can both see the labels and count the selected objects.
![]()
Customizing the interface
The interface of FreeCAD is highly customizable. All panels and toolbars can be moved to different places or stacked one above another. They can also be closed and reopened when needed from the View menu or by right-clicking on an empty area of the interface. There are, however, many more options available, such as creating custom toolbars with tools from any of the Workbenches, or assigning and changing keyboard shortcuts. These advanced customization options are available from the Tools → Customize menu:Read more Getting started with FreeCAD Customizing the interface Workbenches More about Python
The FreeCAD 3D space is a Euclidean space. It has an origin point and three axes: X, Y and Z. If you look at your scene from above, conventionally, the X axis points to the right, the Y axis to the back, and the Z axis upwards. In the lower right corner of the FreeCAD view, you can always see from where you are viewing the scene:
Manual:Navigating in the 3D viewThe point where the three axes meet is the origin. It is the point where the value of all coordinates is zero. For any given axis, moving in one direction will increase the coordinate value and moving in the opposite direction will decrease the coordinate value. Every point of every object that exists in the 3D space can be located by its (x,y,z) coordinates. For example, a point with coordinates (2,3,1) will lie at +2 units on the X axis, +3 units on the Y axis, and +1 unit on the Z axis:
You can look at that scene from any angle, as if you were holding a camera. That camera can be moved left, right, up and down (pan), rotated around what it is pointing at (rotate) and brought closer to or further from the scene (zoom).
The FreeCAD 3D view
Mouse Navigation
Navigating in the FreeCAD 3D view can be done with a mouse, a Space Navigator device, the keyboard, a touchpad, or a combination of those. FreeCAD implements several navigation modes, which determine how the three basic view manipulation operations (pan, rotate and zoom) are done, as well as how selection of objects on the screen is performed. Navigation modes are accessed from the Preferences screen, or directly by right-clicking anywhere on the 3D view:Each of these modes allocates different mouse buttons, or mouse + keyboard combinations, or mouse gestures, to these four operations. The following table shows the principal available modes:
Mode | Pan | Rotate | Zoom | Select |
---|---|---|---|---|
OpenInventor |
|
|
| Hold Ctrl + drag
|
CAD (default) |
|
|
|
|
Blender | Hold Shift + drag
|
|
|
|
Touchpad | Hold Shift + drag
![]() | Alt +
![]() | PgUp / PgDn |
![]() |
Gesture | drag
| drag
|
|
|
OpenCascade |
|
|
|
|
Format | Import | Export | Notes |
---|---|---|---|
STEP | Yes | Yes | This is the most faithful import/export format available, since it supports solid geometry and NURBS. Use it whenever it is possible. |
IGES | Yes | Yes | An older solid format, also very well supported. Some older applications don't support STEP but have IGES. |
BREP | Yes | Yes | The native format of OpenCasCade, FreeCAD's geometry kernel. |
DXF | Yes | Yes | An open format maintained by Autodesk. Since the 3D data inside a DXF file is encoded in proprietary format, FreeCAD can only import/export 2D data to/from this format. |
DWG | Yes | Yes | The proprietary version of DXF. Requires the installation of the Teigha File Converter utility. This format suffers from the same limitations as DXF. |
OBJ | Yes | Yes | A mesh-based format. Can only contain triangulated meshes. All solid and NURBS-based objects of FreeCAD will be converted to mesh on export. An alternative exporter is provided by the Arch workbench, more suited to the export of architectural models. |
DAE | Yes | Yes | The main import/export format of Sketchup. Can only contain triangulated meshes. All solid and NURBS-based objects of FreeCAD will be converted to mesh on export. |
STL | Yes | Yes | A mesh-based format, commonly used for 3D printing. Can only contain triangulated meshes. All solid and NURBS-based objects of FreeCAD will be converted to mesh on export. |
PLY | Yes | Yes | An older mesh-based format. Can only contain triangulated meshes. All solid and NURBS-based objects of FreeCAD will be converted to mesh on export. |
IFC | Yes | Yes | Industry Foundation Classes. Requires the installation of IfcOpenShell-python. The IFC format and its compatibility with other applications is a complex affair, use with care. |
SVG | Yes | Yes | An excellent, widespread 2D graphics format |
VRML | Yes | Yes | A rather old mesh-based web format. |
GCODE | Yes | Yes | FreeCAD can already import and export to/from several flavors of GCode, but only a small number of machines is supported at the moment. |
CSG | Yes | No | OpenSCAD's CSG (Constructive Solid Geometry) format. |
Tool | Description | Tool | Description |
---|---|---|---|
| Draws a box |
| Draws a cone |
| Draws a cylinder |
| Draws a sphere |
| Draws a torus (ring) |
| Creates various other parametric geometric primitives |
| Create more complex shapes from primitives |
| Fuses (unions) two objects |
| Extracts the common (intersection) part of two objects |
| Cuts (subtracts) one object from another |
| Connects interiors of walled objects |
| Embeds a walled object into another walled object |
| Creates a cutout in a wall of an object for another walled object |
| Extrudes planar faces of an object |
| Fillets (rounds) edges of an object |
| Creates a solid by revolving another object (not solid) around an axis |
| Creates a section by intersecting an object with a section plane |
| Creates multiple cross sections along an object |
| Chamfers edges of an object |
| Mirrors the selected object on a given mirror plane |
| Create a ruled surface between selected curves |
| Sweeps one or more profiles along a path |
| Lofts from one profile to another |
| Creates a scaled copy of the original object |
| Assign a thickness to the faces of a shape |
Tool | Description | Tool | Description |
---|---|---|---|
| Draws a line segment between 2 points |
| Draws a line made of multiple line segments (polyline) |
| Draws a circle from center and radius |
| Draws an arc segment from center, radius, start angle and end angle |
| Draws an ellipse from two corner points |
| Draws a regular polygon from a center and a radius |
| Draws a rectangle from 2 opposite points |
| Draws a multi-line text annotation |
| Draws a dimension annotation |
| Draws a B-Spline from a series of points |
| Inserts a single point |
| The ShapeString tool inserts a compound shape representing a text string at a given point in the current document |
| Creates a new object from selected faces on existing objects |
| Draws a Bezier curve from a series of points |
| Moves or copies objects from one location to another |
| Rotates objects by a certain angle around a point |
| Offsets an object to a certain distance |
| Trims, extends or extrudes an object |
| Turns or joins objects into a higher-level object |
| Turns or separates objects into lower-level objects |
| Scales objects in relation to a point |
| Creates a 2D object which is a flattened view of another object |
| Converts a Draft object to a Sketch and vice-versa |
| Creates a rectangular array from an object |
| Creates linked copies of objects |
| Mirrors objects across a line |
Tool | Description | Tool | Description |
---|---|---|---|
| Draws a point |
| Draws a line segment from 2 points |
| Draws an arc segment from center, radius, start angle and end angle |
![]() | Draws an arc segment from two endpoints and another point on the circumference |
| Draws a circle from center and radius |
![]() | Draws a circle from three points on the circumference |
| Draws an ellipse by center point, major radius point and minor radius point |
![]() | Draws an ellipse by major diameter (2 points) and minor radius point |
![]() | Draws an arc of ellipse by center point, major radius point, starting point and ending point |
| Draws a line made of multiple line segments. Several drawing modes available |
| Draws a rectangle from 2 opposite points |
| Draws a regular triangle inscribed in a construction geometry circle |
| Draws a regular square inscribed in a construction geometry circle |
| Draws a regular pentagon inscribed in a construction geometry circle |
| Draws a regular hexagon inscribed in a construction geometry circle |
| Draws a regular heptagon inscribed in a construction geometry circle |
| Draws a regular octagon inscribed in a construction geometry circle |
| Draws an oval by selecting the center of one semicircle and an endpoint of the other semicircle |
| Makes a fillet between two lines joined at one point |
| Trims a line, circle or arc with respect to a clicked point |
| Creates an edge linked to external geometry |
| Toggles an element to/from construction mode. A construction object will not be used in a 3D geometry operation and is only visible while editing the Sketch that contains it |
| Affixes a point onto (coincident with) one or more other points. |
| Affixes a point onto another object such as a line, arc, or axis. |
| Constrains the selected lines or polyline elements to a true vertical orientation. More than one object can be selected before applying this constraint. |
| Constrains the selected lines or polyline elements to a true horizontal orientation. More than one object can be selected before applying this constraint. |
![]() | Constrains two or more lines parallel to one another. |
![]() | Constrains two lines perpendicular to one another, or constrains a line perpendicular to an arc endpoint. |
![]() | Creates a tangent constraint between two selected entities, or a co-linear constraint between two line segments. |
![]() | Constrains two selected entities equal to one another. If used on circles or arcs their radii will be set equal. |
![]() | Constrains two points symmetrically about a line, or constrains the first two selected points symmetrically about a third selected point. |
| Constrains the selected item by setting vertical and horizontal distances relative to the origin, thereby locking the location of that item |
| Fixes the horizontal distance between two points or line endpoints. If only one item is selected, the distance is set to the origin. |
| Fixes the vertical distance between 2 points or line endpoints. If only one item is selected, the distance is set to the origin. |
![]() | Defines the distance of a selected line by constraining its length, or defines the distance between two points by constraining the distance between them. |
![]() | Defines the radius of a selected arc or circle by constraining the radius. |
![]() | Defines the internal angle between two selected lines. |
![]() | Constrains two lines to obey a refraction law to simulate the light going through an interface |
![]() | Aligns selected elements to selected shape (e.g. a line to become major axis of an ellipse) |
| Maps a sketch to the previously selected face of a solid |
| Merge two or more sketches |
| Mirrors selected elements of a sketch |
Tool | Description | Tool | Description |
---|---|---|---|
| Extrudes a solid object from a selected sketch |
| Creates a pocket from a selected sketch. The sketch must be mapped to an existing solid object's face |
| Creates a solid by revolving a sketch around an axis |
| Creates a groove by revolving a sketch around an axis |
| Fillets (rounds) edges of an object |
| Chamfers edges of an object |
| Applies angular draft to faces of an object |
| Mirrors features on a plane or face |
| Creates a linear pattern of features |
| Creates a polar pattern of features |
![]() | Scales features to a different size |
| Allows creating a pattern with any combination of the other transformations |
| Generates a shaft from a table of values and allows to analyze forces and moments |
![]() | Allows you to create several types of gears |
Tool | Description | Tool | Description |
---|---|---|---|
| Creates a wall from scratch or using a selected object as a base |
| Creates a structural element from scratch or using a selected object as a base |
| Creates a reinforcement bar in a selected structural element |
| Creates a floor including selected objects |
| Creates a building including selected objects |
| Creates a site including selected objects |
| Creates a window using a selected object as a base |
| Adds a section plane object to the document |
| Adds an axes system to the document |
| Creates a sloped roof from a selected face |
| Creates a space object in the document |
| Creates a stairs object in the document |
| Creates a panel object from a selected 2D object |
| Creates a frame object from a selected layout |
| Creates an equipment or furniture object |
| Attributes a material to selected objects |
| Creates different types of schedules |
| Cut an object according to a plan |
| Adds objects to a component |
| Subtracts or removes objects from a component |
| Enters or leaves surveying mode |
Tool | Description | Tool | Description |
---|---|---|---|
![]() | Creates a new drawing sheet |
![]() | Inserts a view of the selected object in the active drawing sheet |
![]() | Adds an annotation to the current drawing sheet |
![]() | Adds a clip group to the current drawing sheet |
![]() | Opens a preview of the current sheet in the browser |
![]() | Automatically creates orthographic views of an object on the current drawing sheet |
![]() | Adds the contents of a SVG file as a symbol on the current drawing sheet |
![]() | Inserts a special Draft view of the selected object in the current drawing sheet |
![]() | Saves the current sheet as a SVG file |
true
10
.
Grid spacing 1000mm
to have a one meter-based grid, which is convenient for the size of our building.
Grid size 100 lines
.
On the snapping toolbar make sure the
Tutorial | Topic | Level | Time to complete hh:mm | Authors | FreeCAD version | Example files |
---|---|---|---|---|---|---|
Add FEM Constraint Tutorial | M42kus | |||||
Add FEM Equation Tutorial | JohnWang | |||||
Aeroplane | Part Workbench | Beginner | 0:10 | Hughthecat | ||
Analysis of reinforced concrete with FEM | Reinforced concrete with FEM | Intermediate | 1:00 | HarryvL | 0.19 or above | |
Arch panel tutorial | Modeling an architectural panel | Beginner | 1:00 | Yorik | ||
Arch tutorial | Modeling | Intermediate | Yorik | 0.14 | ||
Basic Attachment Tutorial | Sketch attachment | Beginner/intermediate | 01:00 | Bance | 0.17 and above | Basic Attachment Tutorial.FCStd |
Basic modeling tutorial | Introduction to modelling | Beginner | 0:15 | NormandC | Any | None |
Basic Part Design Tutorial | Modeling | Beginner | Mark Stephen (Quick61) and HarryGeier | 0.17 or above | Basic Part Design for v0.17 | |
Basic Sketcher Tutorial | Sketcher | Beginner | 1:00 | Drei and Vocx | 0.19 | Basic Sketcher tutorial |
Basic TechDraw Tutorial | TechDraw Workbench | Beginner | WandererFan | 0.17 and above | Basic Part Design for v0.17 Sample Basic TechDraw Tutorial Sample | |
Code snippets | Python | Beginner | ||||
Creating a simple part with PartDesign | Modeling | Beginner | 1:00 | GlouGlou | 0.17 or above | Creating a simple PartDesign Body.FCStd |
Customize Toolbars | Beginner | 0:05 | Mario52 | Any | None | |
Draft ShapeString tutorial | Product Design | Beginner | 0:30 | r-frank and vocx | 0.17 and above | Draft_Shapestring_Text |
Draft tutorial | Drafting | Beginner | 0:30 | Drei and vocx | 0.19 | Draft tutorial updated |
Drawing Template HowTo (obsolete) | 2D Drafting | Intermediate | 1:00 | Mark Stephen (Quick61) | 0.14.3700 or above | None |
Drawing tutorial (obsolete) | Blueprints / Drawings | Beginner | 0:15 | Drei | 0.16 or above | |
Dxf Importer Install | Intermediate | 0:05 | Mario52 | Any | None | |
Engine Block Tutorial | Part Workbench | Beginner | 1:00 | Andrewbuck40 | 0.14.3700 | |
Export to STL or OBJ | Export to STL or OBJ | Beginner | 0:20 | r-frank | 0.16.6703 | |
Extend FEM Module | M42kus | |||||
FEM CalculiX Cantilever 3D | Finite Element Analysis | Beginner | 0:10 | Bernd | 0.16.6377 or above | |
FEM Shear of a Composite Block | Finite Element Analysis | Beginner/Intermediate | 0:300 | HarryvL | 0.17.12960 or above | |
FEM tutorial | Finite Element Analysis | Beginner | 0:10 | Drei | 0.16.6700 or above | |
FEM Tutorial Python | Finite Element Analysis | Intermediate | 0:30 | Bernd | 0.18.15985 or above | |
FreeCAD-Ship s60 tutorial | Ship Workbench | Beginner | ||||
FreeCAD-Ship s60 tutorial (II) | Ship Workbench | Beginner | ||||
How to install additional workbenches | Programming | Medium programmer | 0:15 | r-frank | Any | None |
How to install macros | Programming | Medium programmer | 0:15 | Mario52 | Any | None |
Import from STL or OBJ | Import from STL or OBJ | Beginner | 0:30 | r-frank | 1.0 | 0.16.6703 |
Import OpenSCAD code | Import OpenSCAD code | Beginner | 0:30 | r-frank | 0.16.6704 | None |
Import text and geometry from Inkscape | Import text and geometry from Inkscape | Beginner | 0:30 | r-frank | 0.16.6704 | |
Import/Export IFC - compiling IfcOpenShell | Arch Workbench | Advanced | 2:00 | Pablo Gil | ||
Measurement Of Angles On Holes | TechDraw Workbench | Beginner | 0:01 | AnHi | 0.19 | |
PartDesign Bearingholder Tutorial I | Product design - Bearingholder #1 | Beginner | 60 minutes | NormandC | ||
PartDesign Bearingholder Tutorial II | Product design - Bearingholder #2 | Beginner | 60 minutes | NormandC | ||
PartDesign tutorial | Sketcher | Beginner | 0:15 | Drei | 0.16 or above | |
Path Walkthrough for the Impatient | Path Workbench | Chrisb | ||||
Plot Basic tutorial | Plot Workbench Basic Tutorial | Beginner | ||||
Plot MultiAxes tutorial | Plot workbench | Intermediate | ||||
Post-Processing of FEM Results with Paraview | Post-Processing of FEM Results with ParaView | Intermediate | 2:00 | HarryvL | 0.19 | Beam and wall |
Python scripting tutorial | Programming | Intermediate | ||||
Raytracing tutorial | Raytracing | Beginner | 0:010 | Drei | 0.16 or above | |
Robot 6-Axis | Robot Workbench | Intermediate | ||||
Robot tutorial | Robot Workbench | Beginner | r-frank | |||
Scripted Parts: Ball Bearing - Part 1 | Part Scripting - Ball Bearing #1 | Beginner | 0:30 | r-frank | 0.16.6706 | |
Scripted Parts: Ball Bearing - Part 2 | Part Scripting - Ball Bearing #2 | Beginner | 0:30 | r-frank | 0.16.6706 | |
Scripts | Scripting | Beginner | onekk Carlo | 0.19 | ||
Sketcher Micro Tutorial - Constraint Practices | Sketcher | Beginner | 0:30 | Mark Stephen (Quick61) and vocx | 0.19 | Sketcher Constraints practices |
Sketcher reference | ||||||
Sketcher requirement for a sketch | Sketcher | Beginner | Maker | None | ||
Sketcher Tutorial | Sketcher | Beginner | Ulrich | |||
TechDraw pitch circle tutorial | TechDraw Workbench | Beginner | 0:10 | Andergrin | 0.19 | None |
TechDraw TemplateHowTo | TechDraw Workbench | Intermediate | 1:00 | wandererfan | 0.17 | None |
Thread for Screw Tutorial | Product design | Advanced | 1:00 | DeepSOIC, Murdic, vocx | 0.19 | Updated: Thread for screw tutorial |
Toothbrush Head Stand | Modeling | Beginner | 1:00 | EmmanuelG | 0.16 or greater | Thingiverse 2403310 |
Topological data scripting | Programming | Intermediate | ||||
Transient FEM analysis | Transient FEM analysis | |||||
Tutorial custom placing of windows and doors | Architecture | Intermediate | 1:00 | Vocx | 0.18 or above | None |
Tutorial for open windows | Architecture | Beginner | 1:00 | Vocx | 0.18 or above | None |
Tutorial FreeCAD POV ray | Rendering | Intermediate | 2:00 | Vocx | 0.18 or above | None |
Tutorial Render with Blender | Rendering | Intermediate | 1:00 | Vocx | 0.18 or above | None |
VRML Preparation for Robot Simulation | Robot Workbench | Intermediate | 0.11.4252ppa1 | |||
Washers | None | |||||
Whiffle Ball tutorial | Product design | Beginner | 0:30 | r-frank and vocx | 0.17 and above | WhiffleBall_Tutorial_FCWiki.FCStd |
Wikihouse porting tutorial | Wikihouse porting tutorial | Intermediate/Advanced | 1:00 |
Flat Lines
and Wireframe
.
Spreadsheet
, Spreadsheet001
, Spreadsheet002
and so on.
The name can not be changed manually, and it is not visible in the properties of the spreadsheet.
It can be used to refer to the spreadsheet in an Expression (see Spreadsheet data in expressions below.)
The label of a spreadsheet is automatically set to the name of the spreadsheet upon creation.
Unlike the name, the label can be changed, for example in the properties panel or using the context menu action Rename.
Note that the label of a spreadsheet within a document has to be unique; if you try to change the label to a label already used by another spreadsheet, FreeCAD will not accept the new label.
FreeCAD checks for cyclic dependencies.
See Current limitations.
CAD-Data | Cell in Spreadsheet | Result |
---|---|---|
Parametric Length of a Part-Workbench Cube | =MyCube.Length | Length with units mm |
Volume of the Cube | =MyCube.Shape.Volume | Volume in mm³ without units |
Type of the Cube-shape | =MyCube.Shape.ShapeType | String: Solid |
Label of the Cube | =MyCube.Label | String: MyCube |
x-coordinate of center of mass of the Cube | =MyCube.Shape.CenterOfMass.x | x-coordinate in mm without units |
Spreadsheet by Name | Spreadsheet by Label | |
---|---|---|
Cell by Position | =Spreadsheet042.B5
|
=<<MySpreadsheet>>.B5
|
Cell by Alias | =Spreadsheet042.MyAlias
|
=<<MySpreadsheet>>.MyAlias
|
MyObject_Length
would allow the value to be referred to as <<MyParams>>.MyObject_Length
instead of Spreadsheet.B1
.
Besides being much easier to read and understand, alias names are also much easier to change if you decide to adjust the structure of your spreadsheet.
Using an alias also has the advantage that it is reasier to see which cells are used to control other parts of the document.
Note that FreeCAD will automatically adjust the positional references in expressions if you insert or remove rows and columns in the spreadsheet, so even if you use row and column numbers in an expression, you can insert rows and columns without breaking the references to the surrounding cells.
#PENDING
is shown.
You can either recompute manually, using the Std Refresh command, or disable Skip recomputes when you are done editing.
Use a macro to automatically skip recomputes while editing a spreadsheet:
Download and run skipSheet.FCMacro.
This solution saves a few steps compared to the first solution, but also has the mentioned disadvantage.
Put the spreadsheet in a separate FreeCAD file:
You can reference spreadsheet data from an external .FCStd file with this syntax: =NameOfFile#<<MySpreadsheet>>.MyAlias
.
The advantage of having the spreadsheet in another file over switching off recomputes is that the spreadsheet itself does get recomputed.
The disadvantage is that the model won't automatically recompute after changes to the spreadsheet.
In the scenario where you first open the 'spreadsheet' file, change one or more values and then open the 'model' file, there won't be any indication that the model needs to be recomputed.
But if both files are open the Std Refresh icon will update correctly for the 'model' file after changes to the 'spreadsheet' file.
moveViews.py
).
It is possible to have both TechDraw and Drawing Pages in the same FreeCAD document, as each page is completely independent from each other.
There are minor differences in specifying editable texts in SVG templates compared to the Drawing module.
In TechDraw the scaling of the SVG document affects the position of the editable text fields.
See the forum discussion TechDraw templates scale for more details.
Do not cut, copy and paste TechDraw objects in the tree view as this generally does not work out well.
Icon | Name | Topic | Description | Author | Code | ||
---|---|---|---|---|---|---|---|
|
ArchTextures | Architecture and construction | It allows you to add basic, non-photorealistic textures to architectural objects created with the Arch Workbench. | furti | https://github.com/furti/FreeCAD-ArchTextures |
| |
|
BCFPlugin | Architecture and construction | It aims to support the BIM Collaboration Format (BCF). | podestplatz | https://github.com/podestplatz/BCF-Plugin-FreeCAD |
|
|
|
BIM | Architecture and construction | It aims to implement a complete building information modeling (BIM) workflow in FreeCAD. It extends the Arch Workbench, and gathers tools from other workbenches to provide an environment that is convenient to model buildings, and work with IFC files. | yorikvanhavre | https://github.com/yorikvanhavre/BIM_Workbench |
|
|
|
BIMBots | Architecture and construction | It allows you to upload a FreeCAD model or selected parts of a FreeCAD model to a BIMBots instance (usually a BIMServer with external services enabled), and perform different services and analyses on your model, and read the results in FreeCAD, usually under the form of a text report, or a BCF file. | BIMBots | https://github.com/opensourceBIM/BIMbots-FreeCAD |
|
|
|
Dodo | Architecture and construction | It provides tools to create frames (trusses, beams) and pipelines (tubes, elbows, flanges), and query those objects. This is the new version of Flamingo, intended for Python 3 and Qt5. | oddtopus | https://github.com/oddtopus/dodo |
|
|
|
Flamingo | Architecture and construction | It provides tools to create frames (trusses, beams) and pipelines (tubes, elbows, flanges), and query those objects. This is the old version of Dodo, intended for Python 2 and Qt4. You should prefer Dodo for new models. | oddtopus | https://github.com/oddtopus/flamingo |
|
|
GeoData | Architecture and construction | It provides tool to import geographical information from a given point on Earth by its latitude and longitude, of from OpenStreetMap, Google Maps, Bing Map, or Here Map. | microelly2 | https://github.com/microelly2/geodata |
| ||
|
Geomatics | Architecture and construction | It is partially based on the GeoData. It provides functionality specific to Geomatics or Survey engineering, including importing point files, creating surfaces, creating contours, and creating sections. This is partially migrated to the Trails workbench. | HakanSeven12 | https://github.com/HakanSeven12/FreeCAD-Geomatics-Workbench |
|
|
|
OSE Piping | Architecture and construction | Create different piping fittings. It supports Flamingo. | Ruslan | https://github.com/rkrenzler/ose-piping-workbench |
|
|
|
Reinforcement | Architecture and construction | It provides tools for Reinforcement Generation and Detailing. This workbench provides an interface and presets for the creation of common rebar types. And tools to generate rebars bill of material, rebar shape cut list, bar bending schedule, and rebars drawing and dimension. | amrit3701 | https://github.com/amrit3701/FreeCAD-Reinforcement |
|
|
SteelColumn | Architecture and construction | It provides tools for creating complex steel columns assembled from IPE profiles and plates. | ebrahimraeyat | https://github.com/ebrahimraeyat/momen |
|
||
|
Timber | Architecture and construction | It provides tools to facilitate the design and modeling of wood-frame and structural walls. This workbench is no longer developed nor maintained by its author. | j-wiedemann | https://github.com/j-wiedemann/FreeCAD-Timber |
|
|
|
Trails | Architecture and construction | It provides functionality specific to transportation engineering (roads and rail). It includes components to perform analysis of curvature. | joelgraff | https://github.com/joelgraff/freecad.trails |
|
|
|
Wood Frame | Architecture and construction | It provides tools to facilitate the design and modelling of wood-frame and structural walls, as well as cut lists for beams. | JeromeL63 | https://github.com/JeromeL63/Wood-Frame |
| |
|
A2plus | Assembly | It provides tools to create multi-part assemblies. It is a fork and extension of the older Assembly2 Workbench, but it is not compatible with it. | kbwbe | https://github.com/kbwbe/A2plus |
|
|
![]() |
Assembly2 | Assembly | It provides tools to create multi-part assemblies. It is unmaintained since 2016. Consider using A2plus instead. | hamish2014 | https://github.com/hamish2014/FreeCAD_assembly2 |
|
|
|
Assembly3 | Assembly | It is used to perform assembly of different bodies contained in a single file or in multiple documents. It was a testbed for the App Link object that was eventually included in the master code. It is the most complex solution and supports things like interactive kinematics. | realthunder | https://github.com/realthunder/FreeCAD_assembly3 | ||
|
Assembly4 | Assembly | It is a solution based on the enhanced expression engine and the App Link object developed in the branch of Assembly3. Assembly4 does not work with a proper constraint solver, instead it uses the expression engine to position bodies with respect to Local Coordinate Systems (LCS). | Zolko | https://github.com/Zolko-123/FreeCAD_Assembly4 |
|
|
Autoload | Customization | It is a small extension that allows you to select the workbenches that should be loaded when you start FreeCAD. It can be used in combination with other extensions from the same author such as CommandPanel, PieMenu, and ShortCuts. | triplus | https://github.com/triplus/Autoload |
|
||
CommandPanel | Customization | It is an extension that provides a panel that can be used store tools from different workbenches. | triplus | https://github.com/triplus/CommandPanel |
|
||
CubeMenu | Customization | CubeMenu provides the ability to manage the FreeCAD navigation cube menu structure and overall appearance. | triplus | https://github.com/triplus/CubeMenu |
|
||
Glass | Customization | It is an extension that shows the combo view (tree view and property editor) as a transparent overlay over the 3D view. | triplus | https://github.com/triplus/Glass |
|
||
IconThemes | Customization | It is an extension that provides the ability of changing the icons of the default program. Icon sets aren't provided with this extension; these need to be provided separately. | triplus | https://github.com/triplus/IconThemes |
|
||
Launcher | Customization | It is a small extension that provides a dedicated dialog box to search and launch commands. Instead of clicking on a toolbar button or menu entry, this method of executing commands may be faster for some users. | triplus | https://github.com/triplus/Launcher |
|
||
|
ModernUI | Customization | Replaces the standard user interface (UI) with feature such as ribbon menus and collapsing/expanding panels on mouse-over. | HakanSeven12 | https://github.com/HakanSeven12/Modern-UI |
|
|
NavigationIndicator | Customization | It is an extension that adds an indicator for the mouse navigation style in the status bar. Since FreeCAD 0.17 this extension is obsolete, as the indicator is included natively in FreeCAD. | triplus | https://github.com/triplus/NavigationIndicator |
|
| |
PersistentToolbars | Customization | It is a small extension to keep the toolbars in their locations. Since FreeCAD 0.17 this extension is obsolete, as the functionality is included natively in FreeCAD. | triplus | https://github.com/triplus/PersistentToolbars |
|
| |
PieMenu | Customization | It is a small extension that shows a pie menu to select tools or commands when the Tab key is pressed. A pie menu is an interface that appears in Blender and other systems like Android mobile phones to launch commands. | triplus | https://github.com/triplus/PieMenu |
|
||
Pluginloader | Customization | It is a small extension that allows the user to install macros, external workbenches, and other extensions in FreeCAD. Since FreeCAD 0.17 this utility is obsolete, as this functionality is already provided by the Addon Manager. | microelly2 | https://github.com/microelly2/freecad-pluginloader |
|
| |
RemBench | Customization | It is a small extension that remembers and automatically activates a workbench based on the document tab that is selected. | triplus | https://github.com/triplus/RemBench |
|
||
|
SearchBar | Customization | It is an extension that adds a search bar next to the what's this? tool. The search results include tools, objects and preferences. Other mods can extend it by registering a result provider. | Suzanne Soy | https://github.com/SuzanneSoy/SearchBar | ||
SelectorToolbar | Customization | It is a small extension that provides a point and click experience for switching workbenches. | triplus | https://github.com/triplus/SelectorToolbar |
|
||
ShortCuts | Customization | It is a small extension that provides a manager and overlay for shortcuts. | triplus | https://github.com/triplus/ShortCuts |
|
||
TabBar | Customization | It is a small extension that adds a window with tabs in order to select workbenches. | triplus | https://github.com/triplus/TabBar |
|
||
ToolbarStyle | Customization | It is a small extension that allows the configuration of toolbars, with icons, text, or both. | triplus | https://github.com/triplus/ToolbarStyle |
|
||
|
MOOC | Education | It provides an interactive tutorial to learn about FreeCAD directly inside the program. It allows you to evaluate your self-learning. | rockn | https://framagit.org/freecad-france/mooc-workbench |
|
|
|
AirPlaneDesign | Engineering | It is an experimental workbench to design wings and airplane objects. | FredsFactory (a179308) | https://github.com/FredsFactory/FreeCAD_AirPlaneDesign |
|
|
FreeCADTools | Engineering | It contains tools to create metal profiles, square tubing, z profile, palette, rotation, drawing, and more. | Siardeni | https://github.com/Siardeni/FreeCADTools | |||
|
GDML | Engineering | It contains tools to handle the Geometry Definition Markup Language (GDML). | KeithSloan | https://github.com/KeithSloan/GDML |
|
|
|
GDT | Engineering | It is a collection of tools to add geometric dimensioning and tolerancing (GDT) labels in 2D and 3D technical drawings. It implements the standard ISO 16792. | juanvanyo | https://github.com/juanvanyo/FreeCAD-GDT |
|
|
|
Glider | Engineering | It contains tools to design paragliders and kites using the OpenGlider library. | booya | https://github.com/booya-at/OpenGlider | ||
|
KicadStepUp | Engineering | It is aimed at helping both KiCad and FreeCAD users in collaborating with electrical (ECAD) and mechanical (MCAD) design. With FreeCAD it's possible to design a printed circuit board, and push it to KiCad; alternatively, the board can be designed in KiCad, it can be imported by FreeCAD, it can be edited with the Sketcher Workbench, and pushed back into KiCad. The 3D model, boards and enclosure, can be exported to VRML with materials properties for use in KiCad or Blender. | easyw | https://github.com/easyw/kicadStepUpMod |
|
|
|
LCInterlocking | Engineering | It contains tools to create interlocking parts that can be cut with laser-cutters. Tabs and hinges can be added, and the sketch can be exported to SVG. | execuc | https://github.com/execuc/LCInterlocking |
|
|
Maker Workbench | Engineering | The Maker Workbench is composed of a mechatronic components system and an optic components system. The user can modify these components to customize their own system. | David Muñoz | https://github.com/URJCMakerGroup/MakerWorkbench |
|
||
|
OSE 3D Printer | Engineering | A workbench for designing 3D printers by Open Source Ecology for Distributive Enterprise. | G Roques | https://github.com/gbroques/ose-3d-printer-workbench |
|
|
|
Pyrate | Engineering | It is used to design optical lenses. The project aims to provide an optical raytracer for isotropic, homogeneous anisotropic and inhomogeneous isotropic GRIN media. | mess42, joha2 | https://github.com/mess42/pyrate |
|
|
|
Rocket | Engineering | It provides tools for model and amateur rocket design. Users can quickly and easily create rocket components suitable for 3D printing, CNC milling, or laser cutting | DavesRocketShop | https://github.com/davesrocketshop/Rocket.git |
|
|
|
SheetMetal | Engineering | It provides tools to design an object made of a folded sheet, such as a metal case or enclosure. The user starts with a flat sheet, then uses tools to extrude and bend the faces of the object until the desired shape is obtained. The body may then be unfolded to obtain the required flat material, and to use as input for mills or laser cutting machines. | Shai Seger and Ulrich Brammer | https://github.com/shaise/FreeCAD_SheetMetal |
|
|
|
Ship | Engineering | It is used to create structures that are common to ships. It currently is seeking a maintainer. | Jose Luis Cercós Pita | https://github.com/FreeCAD/freecad.ship |
|
|
|
CADExchanger | Information and data | It is an extension that allows FreeCAD to import and export file formats supported by the commercial "CAD Exchanger" application, such as Rhino 3dm or ACIS sat, and mesh formats like OBJ and STL. | yorikvanhavre | https://github.com/yorikvanhavre/CADExchanger |
|
|
dxf_library | Information and data | It installs the DXF Python importer and exporter. This was required in FreeCAD versions v0.15 and below. This is not needed anymore when using the built-in DXF importer in v0.16 and above. This library is still needed if you wish to explicitly use the Python importer, or if you wish to export directly from the 3D model. Please notice that the built-in importer is faster than the Python importer, but in many cases the Python importer produces better results. | yorikvanhavre | https://github.com/yorikvanhavre/Draft-dxf-importer |
|
||
|
DynamicData | Information and data | It is an extension that allows creating container objects to hold custom properties of any type that FreeCAD supports, for example, length or placement. These custom properties can then be used in mathematical expressions just like other properties in the Sketcher Workbench or Spreadsheet Workbench. | mwganson | https://github.com/mwganson/DynamicData |
|
|
|
InventorLoader | Information and data | It is an extension designed to import Autodesk Inventor files. Currently only Parts (IPT) can be displayed, not assemblies (IAM) nor drawings (IDW). As Inventor files contain a complete ACIS model representation, SAT and SAB files can also be imported. Export will not be supported, neither to IPT nor to SAT. | jmplonka | https://github.com/jmplonka/InventorLoader |
|
|
![]() |
ImportNURBS | Information and data | A workbench to add support for importing 3dm files using open rhino3dm library Noteː This workbench is still under development | keithsloan52 | https://github.com/KeithSloan/ImportNURBS |
|
|
|
Plot | Information and data | It is a layer on top of the Matplotlib Python module to graph mathematical functions and vectors of points. | Jose Luis Cercós Pita | https://github.com/FreeCAD/freecad.plot |
|
|
|
Reporting | Information and data | It adds tools to extract information from a FreeCAD document using SQL statements, and show the results in a spreadsheet. The SQL statements can be used from a graphical user interface or from Python scripts. It works in a similar way to the Arch Schedule tool but is more powerful due to the flexibility that SQL provides. | furti | https://github.com/furti/FreeCAD-Reporting |
|
|
|
WebTools | Information and data | It contains a series of tools to communicate with web services like Git, a BIM server, and Sketchfab. | yorikvanhavre | https://github.com/yorikvanhavre/WebTools |
|
|
|
YAML | Information and data | It is an extension that adds an importer to load and manipulate objects from YAML files. In this way it's easier to design and check 3D parts before manufacturing. | Mambix | https://github.com/Mambix/FreeCAD-yaml-workspace |
|
|
3DfindIT | Parts | 3DfindIT.com, the engineering search engine for 3D components from CADENAS, provides users with easy access to millions of CAD models from thousands of international manufacturers and a range of intuitive search methods. | tsielaff, berndhahnebach | https://github.com/cadenasgmbh/3dfindit-freecad-integration |
|
||
|
BOLTSFC | Parts | It is an extension that allows you to use the BOLTS "Open Library for Technical Specifications", which is a collection of objects like nuts, screws, bolts, and so on, parametrically defined. | jreinhardt, berndhahnebach | https://github.com/berndhahnebach/BOLTSFC |
|
|
|
CadQuery | Parts | It allows users to design parametric 3D CAD models defined by the CadQuery CAD scripting API. It includes a full-featured editor with auto-completion, syntax highlighting, line numbering, and code folding. Example scripts are included. Script variables can be edited dynamically through the use of a parameter dialog. This workbench also includes cqparts, which is a library that adds support for parts and assemblies with constraints on top of CadQuery. | jmwright | https://github.com/jmwright/cadquery-freecad-module |
|
|
|
Fasteners Workbench | Parts | It is a workbench that provides various fasteners, screws, bolts, nuts, etc., to attach to your model complying with ISO standards. | Ulrich Bramar (@ulrich1a) and Shai Seger (@shais) | https://github.com/shaise/FreeCAD_FastenersWB |
|
|
|
FCGear | Parts | It is an extension that adds many different gears like cylindric involute, involute rack, cylindric cycloid, spherical involute bevel-gear, and crown gear. | looooo | https://github.com/looooo/freecad.gears |
|
|
Frametools | Parts | It is an extension with tools to create frames and beams, including two intersecting beams, in which one beam is cut by a plane or by another beam. | looooo | https://github.com/looooo/freecad.frametools |
|
||
Parts Library | Parts | It is an extension that downloads a library of parts in STEP format .step or in FreeCAD format .FCStd that can be imported into a document. Users can contribute content to this library by forking the repository, adding their own parts under a permissive CC-BY 3.0 license, and submitting a pull request to merge the new objects. | Community | https://github.com/FreeCAD/FreeCAD-library |
|
||
PCB | Parts | It is a workbench that allows the user to import and create printed circuit boards (PCB) in FreeCAD. It supports layers, colors, transparencies, importing Step and Iges models, and displaying holes and vias. | marmni | https://github.com/marmni/FreeCAD-PCB |
|
||
Retr3d | Parts | It is a framework designed to model and manufacture 3D printable parts starting from electronic waste. The intention of this project is to recycle e-waste, and promote 3D printing, especially in developing economies. | Maaphoo | https://github.com/Maaphoo/Retr3d |
|
||
Stemfie Workbench | Parts | It is a workbench that generates a set of parametric parts for the Stemfie Project. | Stemfie Community | https://github.com/bilbaomakers/StemfieWB | |||
Symbols Library | Parts | It is an extension that downloads a library of SVG symbols that can be used in FreeCAD, particularly in the TechDraw Workbench to produce technical documentation. Users can contribute content to this library by forking the repository, adding their own symbols under a permissive CC-BY 3.0 license, and submitting a pull request to merge the new objects. | Community | https://github.com/FreeCAD/FreeCAD-symbols |
|
||
|
ThreadProfile | Parts | It provides tools to create parametric 2D thread profiles compatible with extrusion tools in Part and PartDesign workbenches. | mwganson | https://github.com/mwganson/ThreadProfile |
|
|
Pivy_trackers | Programming | Pivy_trackers provides a Python developer with an easy way to directly manipulate the Coin3D scenegraph by generating specific scenegraph node structures which are then inserted and accessed though the pivy_tracker classes. | joelgraff | https://github.com/joelgraff/pivy_trackers |
|
||
![]() |
Animation | Pseudo-assembly | It contains many tools to simulate movement of parts, create sequences of pictures, and thus produce an animation. The position and rotation of objects can be changed at different times, but also other properties like visibility, transparency, shape color, and camera position. | microelly2 | https://github.com/microelly2/Animation |
|
|
|
ExplodedAssembly | Pseudo-assembly | It allows creating exploded views and animations of assemblies. It was previously known as "ExplodedAnimation". | JMG1 | https://github.com/JMG1/ExplodedAssembly |
|
|
|
Lattice2 | Pseudo-assembly | It provides tools for working with placements and arrays of placements. It is a sort of assembly workbench but there are no constraints nor relationships. Instead, the workbench focuses in arrays of placements that can be generated, combined, transformed, superimposed, and populated with shapes. It can also create exploded assemblies. | DeepSOIC | https://github.com/DeepSOIC/Lattice2 |
|
|
|
Manipulator | Pseudo-assembly | It is aimed at helping users in aligning, moving, rotating, and measuring 3D objects through a friendly graphical interface. | easyw | https://github.com/easyw/Manipulator |
|
|
|
Part-o-magic | Pseudo-assembly | It is an experimental workbench that provides some improvements to Std Part and PartDesign Body containers (automatic grouping, visibility automation, etc.), in order to work with documents that have multiple parts with deep feature hierarchies. It provides a Body-like container for the Part Workbench, and for other workbenches that produce solid shapes. Part-o-magic does not provide assembly constraints, but the tools included may be useful in conjunction with a true assembly workbench. | DeepSOIC | https://github.com/DeepSOIC/Part-o-magic |
|
|
|
Workfeature | Pseudo-assembly | It provides tools to produce different points, axes, and planes, in order to facilitate the creation of assemblies. This workbench is based on the older Workfeatures macro, which was hosted in the macros recipes page. Currently, the macro has a bit more functionality than the workbench, but eventually the workbench will integrate all existing tools of the macro. They also differ in the graphical user interface; the macro creates a panel next to the tree view and the task panel, while the workbench provides its tools in toolbars, just like other workbenches. | Rentlau | https://github.com/Rentlau/WorkFeature-WB |
|
|
Kerkythea | Rendering | It adds a simple exporter to produce XML files for use with the Kerkythea freeware renderer. | marmni | https://github.com/marmni/FreeCAD-Kerkythea/blob/master/exportToKerkythea.FCMacro |
|
||
|
POV-Ray-Rendering | Rendering | It creates renderings of your FreeCAD model and is very easy to use but also offers all options for advanced users. | The_Raytracers | https://github.com/TheRaytracers/freecad-povray-render |
|
|
|
Render | Rendering | It can produce high-quality rendered images, using open-source external rendering engines like Pov-ray, Luxrender, and Appleseed. Render is a replacement for the Raytracing Workbench, and uses the same templates so they are compatible. In the future Render may also support Kerkythea, Blender's EEVEE, and OpenCascade's CadRays engines. | yorikvanhavre | https://github.com/FreeCAD/FreeCAD-render |
|
|
|
3D Printing Tools | Shapes | It has tools to do small changes to meshes imported from external files like STL. | mark1791 | https://github.com/mark1791/3D_Printing_Tools |
|
|
Cura Engine | Shapes | It is an extension that integrates CuraEngine into FreeCAD in order to facilitate gcode generation for 3D printing. This addon is unmaintained since 2014 and no longer works with recent versions of CuraEngine. | cblt2l | https://github.com/cblt2l/FreeCAD-CuraEngine-Plugin |
|
| |
|
CurvedShapes | Shapes | It has tools to create 3D curves from 2D profiles | chbergmann | https://github.com/chbergmann/CurvedShapesWorkbench |
|
|
|
Curves | Shapes | It is a collection of tools to create and edit NURBS curves and surfaces. | tomate44 (Chris_G) | https://github.com/tomate44/CurvesWB |
|
|
|
Defeaturing | Shapes | It provides tools to edit STEP objects to remove features like holes, faces, and edges, and perform some operations with the simplified objects. | easyw | https://github.com/easyw/Defeaturing_WB |
|
|
|
Design456 | Shapes | Direct modeling tools for FreeCAD. | Mariwan Jalal | https://github.com/MariwanJ/Design456 |
|
|
![]() |
Drawing Dimensioning | Shapes | It adds dimensioning and annotation tools to the Drawing Workbench. It is deprecated since FreeCAD 0.17. Consider using TechDraw Workbench instead. | hamish2014 | https://github.com/hamish2014/FreeCAD_drawing_dimensioning |
|
|
|
Lithophane | Shapes | It is an extension to convert a provided image to a "lithophane" for 3D printing. A lithophane is an image that can only be seen properly when illuminated from behind. | furti | https://github.com/furti/FreeCAD-Lithophane |
|
|
|
MeshRemodel | Shapes | It provides tools to help re-create or re-model imported mesh objects to obtain a solid shape. The workflow is to create points from the mesh's vertices, and use those to create sketches, which can then be extruded. | mwganson | https://github.com/mwganson/MeshRemodel |
|
|
Nurbs | Shapes | It is a collection of scripts for managing freeform surfaces and curves. | microelly2 | https://github.com/microelly2/freecad-nurbs |
|
||
|
Pyramids and Polyhedrons Workbench | Shapes | It has tools for generating pyramids, regular polyhedra and geodesic speres, fully scalable and usable like regular bodies. | eddyverl | https://github.com/eddyverl/FreeCAD-Pyramids-and-Polyhedrons | ||
Reconstruction | Shapes | It provides utilities to reconstruct models from images. | microelly2 | https://github.com/microelly2/reconstruction |
|
| |
|
Silk | Shapes | It is a collection of NURBS surface modeling tools focused on low degree and seam continuity. Silk is the new name of the NURBSlib-EVM project. | edwardvmills | https://github.com/edwardvmills/Silk |
|
|
|
Slic3r-tools | Shapes | It allows exporting parts, and opening the resulting STL in Slic3r. You can set up a default print profile, and directly get information about the resources that would be used to 3D print it, as well as quickly generate the .gcode file. | limikael | https://github.com/limikael/freecad-slic3r-tools |
|
|
SlopedPlanesMacro | Shapes | It allows you to build figures controlling the slopes of the faces of objects. | Damian Caceres Moreno | https://github.com/luzpaz/SlopedPlanesMacro |
|
||
|
Cfd | Simulation | It provides a graphical interface to the OpenFOAM solver to perform computational fluid dynamics (CFD) simulations. | qingfengxia | https://github.com/qingfengxia/Cfd |
|
|
|
CfdOF | Simulation | It is a fork of the Cfd workbench that focuses on ease of use; it is intended for people who are just starting in the world of CFD and OpenFOAM. | jaheyns | https://github.com/jaheyns/CfdOF |
|
|
|
DesignSPHysics | Simulation | It provides a graphical user interface to DualSPHysics, a fluid dynamics solver using the smoothed particle hydrodynamics (SPH) model. | ndrs92 | https://github.com/DualSPHysics/DesignSPHysics |
|
|
|
EM | Simulation | It provides a graphical interface for different solvers by FastFieldSolvers. At present it supports the 3D magneto-quasistatic impedance solver FastHenry. Support for the 3D electrostatic capacitance solver FasterCap is ongoing. | FastFieldSolvers S.R.L. | https://github.com/ediloren/EM-Workbench-for-FreeCAD |
|
|
|
FEM FrontISTR | Simulation | It provides a graphical interface for FrontISTR, an open-source large-scale parallel FEM program for nonlinear structural analysis. | kinagaki | https://github.com/FrontISTR/FEM_FrontISTR |
>>>
symbol which is the command prompt.
Writing code in the interpreter is simple: one line is one instruction.
When you press Enter, your line of code will be executed (after being instantly and invisibly compiled).
For example, try writing this:
print("hello")
print()
is a Python command that, obviously, prints something on the screen.
When you press Enter, the operation is executed, and the message "hello"
is printed.
If you make an error, for example let's write:
print(hello)
Python will immediately tell you so.
In this case Python doesn't know what hello
is.
The " "
characters specify that the content is a string, programming jargon for a piece of text.
Without these the print()
command doesn't recognize hello
.
By pressing the up arrow you can go back to the last line of code and correct it.
The Python interpreter also has a built-in help system.
Let's say we don't understand what went wrong with print(hello)
and we want specific information about the command:
help("print")
You'll get a long and complete description of everything the print()
command can do.
Now that you understand the Python interpreter, we can continue with the more serious stuff.
"hello"
under the name a
.
Now that a
is known we can use it anywhere, for example in the print()
command.
We can use any name we want, we just need to follow some simple rules, such as not using spaces or punctuation and not using Python keywords.
For example, we can write:
hello = "my own version of hello"
print(hello)
Now hello
is not an undefined any more.
Variables can be modified at any time, that's why they are called variables, their content can vary.
For example:
myVariable = "hello"
print(myVariable)
myVariable = "good bye"
print(myVariable)
We changed the value of myVariable
.
We can also copy variables:
var1 = "hello"
var2 = var1
print(var2)
It is advisable to give meaningful names to your variables.
After a while you won't remember what your variable named a
represents.
But if you named it, for example, myWelcomeMessage
you'll easily remember its purpose.
Plus your code is a step closer to being self-documenting.
Case is very important, myVariable
is not the same as myvariable
.
If you were to enter print(myvariable)
it would come back with an error as not defined.
print()
command recognized our "hello"
string.
By using " "
characters, we specified that what follows is a text string.
We can always check the data type of a variable with the type()
command:
myVar = "hello"
type(myVar)
It will tell us the content of myVar
is a 'str'
, which is short for string.
We also have other basic data types such as integer and float numbers:
firstNumber = 10
secondNumber = 20
print(firstNumber + secondNumber)
type(firstNumber)
Python knows that 10 and 20 are integer numbers, so they are stored as 'int'
, and Python can do with them everything it can do with integers.
Look at the results of this:
firstNumber = "10"
secondNumber = "20"
print(firstNumber + secondNumber)
Here we forced Python to consider that our two variables are not numbers but pieces of text.
Python can add two pieces of text together, although in that case, of course, it won't perform any arithmetic.
But we were talking about integer numbers.
There are also float numbers.
The difference is float numbers can have a decimal part and integer numbers do not:
var1 = 13
var2 = 15.65
print("var1 is of type ", type(var1))
print("var2 is of type ", type(var2))
Integers and floats can be mixed together without problems:
total = var1 + var2
print(total)
print(type(total))
Because var2
is a float Python automatically decides that the result must also be a float.
But there are cases where Python does not knows what type to use.
For example:
varA = "hello 123"
varB = 456
print(varA + varB)
This results in an error, varA
is a string and varB
is an integer, and Python doesn't know what to do.
However, we can force Python to convert between types:
varA = "hello"
varB = 123
print(varA + str(varB))
Now that both variables are strings the operation works.
Note that we "stringified" varB
at the time of printing, but we didn't change varB
itself.
If we wanted to turn varB
permanently into a string, we would need to do this:
varB = str(varB)
We can also use int()
and float()
to convert to integer and float if we want:
varA = "123"
print(int(varA))
print(float(varA))
You must have noticed that we have used the print()
command in several ways.
We printed variables, sums, several things separated by commas, and even the result of another Python command.
Maybe you also saw that these two commands:
type(varA)
print(type(varA))
have the same result.
This is because we are in the interpreter, and everything is automatically printed.
When we write more complex programs that run outside the interpreter, they won't print automatically, so we'll need to use the print()
command.
With that in mind let's stop using it here.
From now on we will simply write:
myVar = "hello friends"
myVar
[ ]
:
myList = [1, 2, 3]
type(myList)
myOtherList = ["Bart", "Frank", "Bob"]
myMixedList = ["hello", 345, 34.567]
As you can see a list can contain any type of data.
You can do many things with a list.
For example, count its items:
len(myOtherList)
Or retrieve one item:
myName = myOtherList[0]
myFriendsName = myOtherList[1]
While the len()
command returns the total number of items in a list, the first item in a list is always at position 0
, so in our myOtherList
"Bob"
will be at position 2
.
We can do much more with lists such as sorting items and removing or adding items.
Interestingly a text string is very similar to a list of characters in Python.
Try doing this:
myvar = "hello"
len(myvar)
myvar[2]
Usually what you can do with lists can also be done with strings.
In fact both lists and strings are sequences.
Apart from strings, integers, floats and lists, there are more built-in data types, such as dictionaries, and you can even create your own data types with classes.
for in
command and did something with each of the items.
Note the special syntax: the for
command terminates with :
indicating the following will be a block of one of more commands.
In the interpreter, immediately after you enter the command line ending with :
, the command prompt will change to ...
which means Python knows that there is more to come.
How will Python know how many of the next lines will need to be executed inside the for in
operation? For that, Python relies on indentation.
The next lines must begin with a blank space, or several blank spaces, or a tab, or several tabs.
And as long as the indentation stays the same the lines will be considered part of the for in
block.
If you begin one line with 2 spaces and the next one with 4, there will be an error.
When you have finished, just write another line without indentation, or press Enter to come back from the for in
block
Indentation also aids in program readability.
If you use large indentations (for example use tabs instead of spaces) when you write a big program, you'll have a clear view of what is executed inside what.
We'll see that other commands use indented blocks of code as well.
The for in
command can be used for many things that must be done more than once.
It can, for example, be combined with the range()
command:
serie = range(1, 11)
total = 0
print("sum")
for number in serie:
print(number)
total = total + number
print("----")
print(total)
If you have been running the code examples in an interpreter by copy-pasting, you will find the previous block of text will throw an error.
Instead, copy to the end of the indented block, i.e.
the end of the line total = total + number
and then paste in the interpreter.
In the interpreter press Enter until the three dot prompt disappears and the code runs.
Then copy the final two lines followed by another Enter.
The final answer should appear.
If you type into the interpreter help(range)
you will see:
range(...)
range(stop) -> list of integers
range(start, stop[, step]) -> list of integers
Here the square brackets denote an optional parameter.
However all are expected to be integers.
Below we will force the step parameter to be an integer using int()
:
number = 1000
for i in range(0, 180 * number, int(0.5 * number)):
print(float(i) / number)
Another range()
example:
alldaltons = ["Joe", "William", "Jack", "Averell"]
for n in range(4):
print(alldaltons[n], " is Dalton number ", n)
The range()
command also has that strange particularity that it begins with 0
(if you don't specify the starting number) and that its last number will be one less than the ending number you specify.
That is, of course, so it works well with other Python commands.
For example:
alldaltons = ["Joe", "William", "Jack", "Averell"]
total = len(alldaltons)
for n in range(total):
print(alldaltons[n])
Another interesting use of indented blocks is with the if
command.
This command executes a code block only if a certain condition is met, for example:
alldaltons = ["Joe", "William", "Jack", "Averell"]
if "Joe" in alldaltons:
print("We found that Dalton!!!")
Of course this will always print the sentence, but try replacing the second line with:
if "Lucky" in alldaltons:
Then nothing is printed.
We can also specify an else
statement:
alldaltons = ["Joe", "William", "Jack", "Averell"]
if "Lucky" in alldaltons:
print("We found that Dalton!!!")
else:
print("Such Dalton doesn't exist!")
def()
command defines a new function, you give it a name, and inside the parenthesis you define the arguments that the function will use.
Arguments are data that will be passed to the function.
For example, look at the len()
command.
If you just write len()
, Python will tell you it needs an argument.
Which is obvious: you want to know the length of something.
If you write len(myList)
then myList
is the argument that you pass to the len()
function.
And the len()
function is defined in such a way that it knows what to do with this argument.
We have done the same thing with our printsqm
function.
The myValue
name can be anything, and it will only be used inside the function.
It is just a name you give to the argument so you can do something with it.
By defining arguments you also to tell the function how many to expect.
For example, if you do this:
printsqm(45, 34)
there will be an error.
Our function was programmed to receive just one argument, but it received two, 45
and 34
.
Let's try another example:
def sum(val1, val2):
total = val1 + val2
return total
myTotal = sum(45, 34)
Here we made a function that receives two arguments, sums them, and returns that value.
Returning something is very useful, because we can do something with the result, such as store it in the myTotal
variable.
sum()
function in the interpreter, we execute it like this:
sum(14, 45)
But when we import a module containing a sum()
function the syntax is a bit different:
myTest.sum(14, 45)
That is, the module is imported as a "container", and all its functions are inside that container.
This is very useful, because we can import a lot of modules, and keep everything well organized.
Basically when you see something.somethingElse
, with a dot in between, then this means somethingElse
is inside something
.
We can also import our sum() function directly into the main interpreter space:
from myTest import *
sum(12, 54)
Almost all modules do that: they define functions, new data types and classes that you can use in the interpreter or in your own Python modules, because nothing prevents you from importing other modules inside your module!
How do we know what modules we have, what functions are inside and how to use them (that is, what kind of arguments they need)? We have already seen that Python has a help()
function.
Doing:
help("modules")
will give us a list of all available modules.
We can import any of them and browse their content with the dir()
command:
import math
dir(math)
We'll see all the functions contained in the math
module, as well as strange stuff named __doc__
, __file__
, __name__
.
Every function in a well made module has a __doc__
that explains how to use it.
For example, we see that there is a sin()
function inside the math module.
Want to know how to use it?
print(math.sin.__doc__)
It may not be evident, but on either side of doc
are two underscore characters.
And finally one last tip: When working on new or existing code, it is better to not use the FreeCAD macro file extension, .FCMacro, but instead use the standard .py extension.
This is because Python doesn't recognize the .FCMacro extension.
If you use .py your code can be easily loaded with import
, as we have already seen, and also reloaded with importlib.reload()
:
import importlib
importlib.reload(myTest)
There is however an alternative:
exec(open("C:/PathToMyMacro/myMacro.FCMacro").read())
App.
or Gui.
and see what happens.
Another more generic Python way of exploring the content of modules and classes is to use the print(dir())
command.
For example, typing print(dir())
will list all modules currently loaded in FreeCAD.
print(dir(App))
will show you everything inside the App module, etc.
Another useful feature of the interpreter is the possibility to go back through the command history and retrieve a line of code that you already typed earlier.
To navigate through the command history, just use Up arrow or Down arrow.
By right-clicking in the interpreter window, you also have several other options, such as copy the entire history (useful when you want to experiment with things before making a full script of them), or insert a filename with complete path.
App
, and GUI functionality, named Gui
.
These two modules can also be accessed from scripts outside of the interpreter, by the names FreeCAD
and FreeCADGui
respectively.
In the App
module you'll find everything related to the application itself, like methods for opening or closing files, and to the documents, like setting the active document or listing their contents.
In the Gui
module, you'll find tools for accessing and managing Gui elements, like the workbenches and their toolbars, and, more interestingly, the graphical representation of all FreeCAD content.
Listing the content of these modules is not very useful because they grow quite fast as FreeCAD develops.
But the two browsing tools provided (the class browser and the Python help) should give you complete and up-to-date documentation at any moment.
App
module, and change the way they are represented on screen via the Gui
module.
For example, a cube has properties that define it (like width, length, height) that are stored in an App
object, and representation properties (like faces color, drawing mode) that are stored in a corresponding Gui
object.
This way of doing things allows a very wide range of uses, like having algorithms work only on the definition part of features, without the need to care about any visual part, or even redirect the content of the document to non-graphical application, such as lists, spreadsheets, or element analysis.
For every App
object in your document, there exists a corresponding Gui
object.
In fact the document itself has both an App
and a Gui
object.
This, of course, only applies when you run FreeCAD with its full interface.
In the command-line version no GUI exists, so only App
objects are available.
Note that the Gui
part of objects is re-generated every time an App
object is marked as 'to be recomputed' (for example when one of its parameters changes), so any changes made directly to the Gui
object may be lost.
To access the App
part of something, you type:
myObject = App.ActiveDocument.getObject("ObjectName")
where "ObjectName"
is the name of your object.
You can also type:
myObject = App.ActiveDocument.ObjectName
To access the Gui
part of the same object, you type:
myViewObject = Gui.ActiveDocument.getObject("ObjectName")
where "ObjectName"
is the name of your object.
You can also type:
myViewObject = App.ActiveDocument.ObjectName.ViewObject
If you are in command-line mode and have no GUI, the last line will return None
.
App
and Gui
objects.
The App
object contains your actual geometry definitions, while the Gui
object contains the different views of your document.
You can open several windows, each one viewing your work with a different zoom factor or from a different direction.
These views are all part of your document's Gui
object.
To access the App
part of the currently open (active) document, you type:
myDocument = App.ActiveDocument
To create a new document, type:
myDocument = App.newDocument("Document Name")
To access the Gui
part of the currently open (active) document, you type:
myGuiDocument = Gui.ActiveDocument
To access the current view, you type:
myView = Gui.ActiveDocument.ActiveView
FreeCAD
and FreeCADGui
modules are only responsible for creating and managing objects in the FreeCAD document.
They don't actually do anything more such as creating or modifying geometry.
This is because that geometry can be of several types, and therefore requires additional modules, each responsible for managing a certain geometry type.
For example, the Part Workbench, using the OpenCascade kernel, is able to create and manipulate BRep type geometry.
Whereas the Mesh Workbench is able to build and modify mesh objects.
In this manner FreeCAD is able to handle a wide variety of object types, that can all coexist in the same document, and new types can easily be added in the future.
Mesh
module) and a part (handled by the Part
module):
myMesh = FreeCAD.ActiveDocument.addObject("Mesh::Feature", "myMeshName")
myPart = FreeCAD.ActiveDocument.addObject("Part::Feature", "myPartName")
The first argument is the object type, the second the name of the object.
Our two objects look almost the same: They don't contain any geometry yet, and most of their properties are the same when you inspect them with dir(myMesh)
and dir(myPart)
.
Except for one thing, myMesh
has a Mesh
property and myPart
has a Shape
property.
That is where the Mesh and Part data are stored.
For example, let's create a Part
cube and store it in our myPart
object:
import Part
cube = Part.makeBox(2, 2, 2)
myPart.Shape = cube
You could try storing the cube inside the Mesh
property of the myMesh
object, but it will return an error.
That is because each properties is made to store only a certain type.
In a Mesh
property, you can only save stuff created with the Mesh
module.
Note that most modules also have a shortcut to add their geometry to the document:
import Part
cube = Part.makeBox(2, 2, 2)
Part.show(cube)
.py
extension, FreeCAD macros should have the .FCMacro
extension.
A collection of macros written by experienced users is found in the macros recipes page.
See the Power users hub to learn more about the Python programming language, and about writing macros.
In particular, you should start with these pages:
Introduction to Python
Python scripting tutorial
FreeCAD Scripting Basics
make...()
methods from the Part module:
b = Part.makeBox(100, 100, 100)
Part.show(b)
Some available make...()
methods:
makeBox(l, w, h, [p, d])
Makes a box located in p and pointing into the direction d with the dimensions (l,w,h).
makeCircle(radius)
Makes a circle with a given radius.
makeCone(radius1, radius2, height)
Makes a cone with the given radii and height.
makeCylinder(radius, height)
Makes a cylinder with a given radius and height.
makeLine((x1, y1, z1), (x2, y2, z2))
Makes a line from two points.
makePlane(length, width)
Makes a plane with length and width.
makePolygon(list)
Makes a polygon from a list of points.
makeSphere(radius)
Makes a sphere with a given radius.
makeTorus(radius1, radius2)
Makes a torus with the given radii.
See the Part API page for a complete list of available methods of the Part module.
Part.show(wire3)
will display the 4 edges that compose our wire.
Other useful information can be easily retrieved:
wire3.Length
> 40.0
wire3.CenterOfMass
> Vector (5, 5, 0)
wire3.isClosed()
> True
wire2.isClosed()
> False
makeCircle()
only accepts Base.Vector()
for the position
and normal parameters, not tuples.
You can also create part of the circle by giving a start and an end angle:
from math import pi
arc1 = Part.makeCircle(10, Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), 0, 180)
arc2 = Part.makeCircle(10, Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), 180, 360)
Angles should be provided in degrees.
If you have radians simply convert them using the formula:
degrees = radians * 180/pi
or by using Python's math
module:
import math
degrees = math.degrees(radians)
makeArc()
function, but we have the Part.Arc()
function to create an arc through three points.
It creates an arc object joining the start point to the end point through the middle point.
The arc object's toShape()
function must be called to get an edge object, the same as when using Part.LineSegment
instead of Part.makeLine
.
arc = Part.Arc(Base.Vector(0, 0, 0), Base.Vector(0, 5, 0), Base.Vector(5, 5, 0))
arc
> <Arc object>
arc_edge = arc.toShape()
Part.show(arc_edge)
Arc()
only accepts Base.Vector()
for points and not tuples.
You can also obtain an arc by using a portion of a circle:
from math import pi
circle = Part.Circle(Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), 10)
arc = Part.Arc(circle,0,pi)
Arcs are valid edges like lines, so they can be used in wires also.
makePolygon()
function takes a list of points and creates a wire through those points:
lshape_wire = Part.makePolygon([Base.Vector(0, 5, 0), Base.Vector(0, 0, 0), Base.Vector(5, 0, 0)])
Part.BezierCurve()
from a series of FreeCAD.Vector()
points.
Note: when "getting" and "setting" a single pole or weight, indices start at 1, not 0.
def makeBCurveEdge(Points):
geomCurve = Part.BezierCurve()
geomCurve.setPoles(Points)
edge = Part.Edge(geomCurve)
return(edge)
makePlane(length, width, [start_pnt, dir_normal])
.
By default start_pnt = Vector(0, 0, 0) and dir_normal = Vector(0, 0, 1).
Using dir_normal = Vector(0, 0, 1) will create the plane facing in the positive Z axis direction, while dir_normal = Vector(1, 0, 0) will create the plane facing in the positive X axis direction:
plane = Part.makePlane(2, 2)
plane
> <Face object at 028AF990>
plane = Part.makePlane(2, 2, Base.Vector(3, 0, 0), Base.Vector(0, 1, 0))
plane.BoundBox
> BoundBox (3, 0, 0, 5, 0, 2)
BoundBox
is a cuboid enclosing the plane with a diagonal starting at (3, 0, 0) and ending at (5, 0, 2).
Here the BoundBox
thickness along the Y axis is zero, since our shape is totally flat.
Note: makePlane()
only accepts Base.Vector()
for start_pnt and dir_normal and not tuples.
Arc
, Ellipse
creates an ellipse object not an edge, so we need to convert it into an edge using toShape()
for display.
Note: Ellipse()
only accepts Base.Vector()
for points and not tuples.
eli = Part.Ellipse(Base.Vector(0, 0, 0), 10, 5)
Part.show(eli.toShape())
For the above Ellipse constructor we have passed center, MajorRadius and MinorRadius.
makeTorus(radius1, radius2, [pnt, dir, angle1, angle2, angle])
.
By default pnt = Vector(0, 0, 0), dir = Vector(0, 0, 1), angle1 = 0, angle2 = 360 and angle = 360.
Consider a torus as small circle sweeping along a big circle.
Radius1 is the radius of the big circle, radius2 is the radius of the small circle, pnt is the center of the torus and dir is the normal direction.
angle1 and angle2 are angles in degrees for the small circle; the last angle parameter is to make a section of the torus:
torus = Part.makeTorus(10, 2)
The above code will create a torus with diameter 20 (radius 10) and thickness 4 (small circle radius 2)
tor=Part.makeTorus(10, 5, Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), 0, 180)
The above code will create a slice of the torus.
tor=Part.makeTorus(10, 5, Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), 0, 360, 180)
The above code will create a semi torus; only the last parameter is changed.
i.e the remaining angles are defaults.
Giving the angle 180 will create the torus from 0 to 180, that is, a half torus.
makeBox(length, width, height, [pnt, dir])
.
By default pnt = Vector(0, 0, 0) and dir = Vector(0, 0, 1).
box = Part.makeBox(10, 10, 10)
len(box.Vertexes)
> 8
makeSphere(radius, [pnt, dir, angle1, angle2, angle3])
.
By default pnt = Vector(0, 0, 0), dir = Vector(0, 0, 1), angle1 = -90, angle2 = 90 and angle3 = 360.
Angle1 and angle2 are the vertical minimum and maximum of the sphere, angle3 is the sphere diameter.
sphere = Part.makeSphere(10)
hemisphere = Part.makeSphere(10, Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), -90, 90, 180)
makeCylinder(radius, height, [pnt, dir, angle])
.
By default pnt = Vector(0, 0, 0), dir = Vector(0, 0, 1) and angle = 360.
cylinder = Part.makeCylinder(5, 20)
partCylinder = Part.makeCylinder(5, 20, Base.Vector(20, 0, 0), Base.Vector(0, 0, 1), 180)
makeCone(radius1, radius2, height, [pnt, dir, angle])
.
By default pnt = Vector(0, 0, 0), dir = Vector(0, 0, 1) and angle = 360.
cone = Part.makeCone(10, 0, 20)
semicone = Part.makeCone(10, 0, 20, Base.Vector(20, 0, 0), Base.Vector(0, 0, 1), 180)
transformShape()
and transformGeometry()
.
The difference
is that with the first one, you are sure that no deformations will occur (see Scaling a shape below).
We can apply our transformation like this:
myShape.transformShape(myMat)
or
myShape.transformGeometry(myMat)
transformShape()
, we must use transformGeometry()
:
myMat = Base.Matrix()
myMat.scale(2, 1, 1)
myShape=myShape.transformGeometry(myMat)
makeBox()
command created a solid shape.
This solid, like all Part solids, contains faces.
Faces always contain wires, which are lists of edges that border the face.
Each face has at least one closed wire (it can have more if the face has a hole).
In the wire, we can look at each edge separately, and inside each edge, we can see the vertices.
Straight edges have only two vertices, obviously.
Part
module, but also the FreeCAD.Base
module, which contains basic FreeCAD structures like vectors and matrices.
def makeBottleTut(myWidth = 50.0, myHeight = 70.0, myThickness = 30.0):
aPnt1=Base.Vector(-myWidth / 2., 0, 0)
aPnt2=Base.Vector(-myWidth / 2., -myThickness / 4., 0)
aPnt3=Base.Vector(0, -myThickness / 2., 0)
aPnt4=Base.Vector(myWidth / 2., -myThickness / 4., 0)
aPnt5=Base.Vector(myWidth / 2., 0, 0)
Here we define our makeBottleTut
function.
This function can be called without arguments, like we did above, in which case default values for width, height, and thickness will be used.
Then, we define a couple of points that will be used for building our base profile.
...
aArcOfCircle = Part.Arc(aPnt2, aPnt3, aPnt4)
aSegment1=Part.LineSegment(aPnt1, aPnt2)
aSegment2=Part.LineSegment(aPnt4, aPnt5)
Here we define the geometry: an arc, made of three points, and two line segments, made of two points.
...
aEdge1=aSegment1.toShape()
aEdge2=aArcOfCircle.toShape()
aEdge3=aSegment2.toShape()
aWire=Part.Wire([aEdge1, aEdge2, aEdge3])
Remember the difference between geometry and shapes? Here we build shapes out of our construction geometry.
Three edges (edges can be straight or curved), then a wire made of those three edges.
...
aTrsf=Base.Matrix()
aTrsf.rotateZ(math.pi) # rotate around the z-axis
aMirroredWire=aWire.copy()
aMirroredWire.transformShape(aTrsf)
myWireProfile=Part.Wire([aWire, aMirroredWire])
So far we have built only a half profile.
Instead of building the whole profile the same way, we can just mirror what we did and glue both halves together.
We first create a matrix.
A matrix is a very common way to apply transformations to objects in the 3D world, since it can contain in one structure all basic transformations that 3D objects can undergo (move, rotate and scale).
After we create the matrix we mirror it, then we create a copy of our wire and apply the transformation matrix to it.
We now have two wires, and we can make a third wire out of them, since wires are actually lists of edges.
...
myFaceProfile=Part.Face(myWireProfile)
aPrismVec=Base.Vector(0, 0, myHeight)
myBody=myFaceProfile.extrude(aPrismVec)
myBody=myBody.makeFillet(myThickness / 12.0, myBody.Edges)
Now that we have a closed wire, it can be turned into a face.
Once we have a face, we can extrude it.
In doing so, we make a solid.
Then we apply a nice little fillet to our object because we care about good design, don't we?
...
neckLocation=Base.Vector(0, 0, myHeight)
neckNormal=Base.Vector(0, 0, 1)
myNeckRadius = myThickness / 4.
myNeckHeight = myHeight / 10.
myNeck = Part.makeCylinder(myNeckRadius, myNeckHeight, neckLocation, neckNormal)
At this point, the body of our bottle is made, but we still need to create a neck.
So we make a new solid, with a cylinder.
...
myBody = myBody.fuse(myNeck)
The fuse operation is very powerful.
It will take care of gluing what needs to be glued and remove parts that need to be removed.
...
return myBody
Then, we return our Part solid as the result of our function.
el = makeBottleTut()
Part.show(el)
Finally, we call the function to actually create the part, then make it visible.
exportBrep()
, exportIges()
, exportStep()
and exportStl()
methods available for all shape objects.
So, doing:
import Part
s = Part.makeBox(10, 10, 10)
s.exportStep("test.stp")
will save our box into a STEP file.
To load a BREP, IGES or STEP file:
import Part
s = Part.Shape()
s.read("test.stp")
To convert a STEP file to an IGS file:
import Part
s = Part.Shape()
s.read("file.stp") # incoming file igs, stp, stl, brep
s.exportIges("file.igs") # outbound file igs
PySide
module provides support for Qt4, while PySide2
provides support for Qt5.
However, in FreeCAD there is no need to use PySide2
directly, as a special PySide
module is included to handle Qt5.
This PySide
module is located in the Ext/
directory of an installation of FreeCAD compiled for Qt5.
/usr/share/freecad/Ext/PySide
This module just imports the necessary classes from PySide2
, and places them in the PySide
namespace.
This means that in most cases the same code can be used with both Qt4 and Qt5, as long as we use the single PySide
module.
PySide2.QtCore -> PySide.QtCore
PySide2.QtGui -> PySide.QtGui
PySide2.QtSvg -> PySide.QtSvg
PySide2.QtUiTools -> PySide.QtUiTools
The only unusual aspect is that the PySide2.QtWidgets
classes are placed in the PySide.QtGui
namespace.
PySide2.QtWidgets.QCheckBox -> PySide.QtGui.QCheckBox
]
__init__
function as it is not called automatically.
This example does not require it because the onChanged
method of the Box
class has the same effect as the execute
function, but the examples below rely on being recomputed before anything is displayed in the 3D view.
In the examples, this is done manually with ActiveDocument.recompute()
but in more complex scenarios you need to decide where to recompute either the whole document or the FeaturePython object.
This example produces a number of exception stack traces in the report view window.
This is because the onChanged
method of the Box
class is called each time a property is added in __init__
.
When the first one is added, the Width and Height properties don't exist yet and so the attempt to access them fails.
An explanation of __getstate__
and __setstate__
is in the forum thread obj.Proxy.Type is a dict, not a string.
getDetailPath
, which converts from a string path to an array of scenegraph objects, and getElementPicked
, which takes an element which has been clicked on in the scenegraph and returns its string name (note, not its string path).
Here is the molecule example above, adapted to make the elements of the molecule selectable:
class Molecule:
def __init__(self, obj):
''' Add two point properties '''
obj.addProperty("App::PropertyVector","p1","Line","Start point")
obj.addProperty("App::PropertyVector","p2","Line","End point").p2=FreeCAD.Vector(5,0,0)
obj.Proxy = self
def onChanged(self, fp, prop):
if prop == "p1" or prop == "p2":
''' Print the name of the property that has changed '''
fp.Shape = Part.makeLine(fp.p1,fp.p2)
def execute(self, fp):
''' Print a short message when doing a recomputation, this method is mandatory '''
fp.Shape = Part.makeLine(fp.p1,fp.p2)
class ViewProviderMolecule:
def __init__(self, obj):
''' Set this object to the proxy object of the actual view provider '''
obj.Proxy = self
self.ViewObject = obj
sep1=coin.SoSeparator()
sel1 = coin.SoType.fromName('SoFCSelection').createInstance()
# sel1.policy.setValue(coin.SoSelection.SHIFT)
sel1.ref()
sep1.addChild(sel1)
self.trl1=coin.SoTranslation()
sel1.addChild(self.trl1)
sel1.addChild(coin.SoSphere())
sep2=coin.SoSeparator()
sel2 = coin.SoType.fromName('SoFCSelection').createInstance()
sel2.ref()
sep2.addChild(sel2)
self.trl2=coin.SoTranslation()
sel2.addChild(self.trl2)
sel2.addChild(coin.SoSphere())
obj.RootNode.addChild(sep1)
obj.RootNode.addChild(sep2)
self.updateData(obj.Object, 'p2')
self.sel1 = sel1
self.sel2 = sel2
def getDetailPath(self, subname, path, append):
vobj = self.ViewObject
if append:
path.append(vobj.RootNode)
path.append(vobj.SwitchNode)
mode = vobj.SwitchNode.whichChild.getValue()
if mode >= 0:
mode = vobj.SwitchNode.getChild(mode)
path.append(mode)
sub = Part.splitSubname(subname)[-1]
if sub == 'Atom1':
path.append(self.sel1)
elif sub == 'Atom2':
path.append(self.sel2)
else:
path.append(mode.getChild(0))
return True
def getElementPicked(self, pp):
path = pp.getPath()
if path.findNode(self.sel1) >= 0:
return 'Atom1'
if path.findNode(self.sel2) >= 0:
return 'Atom2'
raise NotImplementedError
def updateData(self, fp, prop):
"If a property of the handled feature has changed we have the chance to handle this here"
# fp is the handled feature, prop is the name of the property that has changed
if prop == "p1":
p = fp.getPropertyByName("p1")
self.trl1.translation=(p.x,p.y,p.z)
elif prop == "p2":
p = fp.getPropertyByName("p2")
self.trl2.translation=(p.x,p.y,p.z)
def __getstate__(self):
return None
def __setstate__(self,state):
return None
def makeMolecule():
FreeCAD.newDocument()
a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Molecule")
Molecule(a)
ViewProviderMolecule(a.ViewObject)
FreeCAD.ActiveDocument.recompute()
obj.addDisplayMode(node, "modename")
while others use obj.SwitchNode.getChild(x).addChild(y)
.
Each feature in a FreeCAD document is based the following scenegraph structure:
RootNode
\- SwitchNode
\- Shaded
- Wireframe
- etc
The SwitchNode
displays only one of its children, depending on which display mode is selection in FreeCAD.
The examples which use addDisplayMode
are constructing their scenegraphs solely out of coin3d scenegraph elements.
Under the covers, addDisplayMode
adds a new child to the SwitchNode
; the name of that node will match the display mode it was passed.
The examples which use SwitchNode.getChild(x).addChild
also construct part of their geometry using functions from the Part workbench, such as fp.Shape = Part.makeLine(fp.p1,fp.p2)
.
This constructs the different display mode scenegraphs under the SwitchNode
; when we later come to add coin3d elements to the scenegraph, we need to add them to the existing display mode scenegraphs using addChild
rather than creating a new child of the SwitchNode
.
When using addDisplayMode()
to add geometry to the scenegraph, each display mode should have its own node which is passed to addDisplayMode()
; don't reuse the same node for this.
Doing so will confuse the selection mechanism.
It's okay if each display mode's node has the same geometry nodes added below it, just the root of each display mode needs to be distinct.
Here is the above molecule example, adapted to be drawn only with Coin3D scenegraph objects instead of using objects from the Part workbench:
import Part
from pivy import coin
class Molecule:
def __init__(self, obj):
''' Add two point properties '''
obj.addProperty("App::PropertyVector","p1","Line","Start point")
obj.addProperty("App::PropertyVector","p2","Line","End point").p2=FreeCAD.Vector(5,0,0)
obj.Proxy = self
def onChanged(self, fp, prop):
pass
def execute(self, fp):
''' Print a short message when doing a recomputation, this method is mandatory '''
pass
class ViewProviderMolecule:
def __init__(self, obj):
''' Set this object to the proxy object of the actual view provider '''
self.constructed = False
obj.Proxy = self
self.ViewObject = obj
def attach(self, obj):
material = coin.SoMaterial()
material.diffuseColor = (1.0, 0.0, 0.0)
material.emissiveColor = (1.0, 0.0, 0.0)
drawStyle = coin.SoDrawStyle()
drawStyle.pointSize.setValue(10)
drawStyle.style = coin.SoDrawStyle.LINES
wireframe = coin.SoGroup()
shaded = coin.SoGroup()
self.wireframe = wireframe
self.shaded = shaded
self.coords = coin.SoCoordinate3()
self.coords.point.setValues(0, 2, [FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(1, 0, 0)])
wireframe += self.coords
wireframe += drawStyle
wireframe += material
shaded += self.coords
shaded += drawStyle
shaded += material
g = coin.SoGroup()
sel1 = coin.SoType.fromName('SoFCSelection').createInstance()
sel1.style = 'EMISSIVE_DIFFUSE'
p1 = coin.SoType.fromName('SoIndexedPointSet').createInstance()
p1.coordIndex.set1Value(0, 0)
sel1 += p1
g += sel1
wireframe += g
shaded += g
g = coin.SoGroup()
sel2 = coin.SoType.fromName('SoFCSelection').createInstance()
sel2.style = 'EMISSIVE_DIFFUSE'
p2 = coin.SoType.fromName('SoIndexedPointSet').createInstance()
p2.coordIndex.set1Value(0, 1)
sel2 += p2
g += sel2
wireframe += g
shaded += g
g = coin.SoGroup()
sel3 = coin.SoType.fromName('SoFCSelection').createInstance()
sel3.style = 'EMISSIVE_DIFFUSE'
p3 = coin.SoType.fromName('SoIndexedLineSet').createInstance()
p3.coordIndex.setValues(0, 2, [0, 1])
sel3 += p3
g += sel3
wireframe += g
shaded += g
obj.addDisplayMode(wireframe, 'Wireframe')
obj.addDisplayMode(shaded, 'Shaded')
self.sel1 = sel1
self.sel2 = sel2
self.sel3 = sel3
self.constructed = True
self.updateData(obj.Object, 'p2')
def getDetailPath(self, subname, path, append):
vobj = self.ViewObject
if append:
path.append(vobj.RootNode)
path.append(vobj.SwitchNode)
mode = vobj.SwitchNode.whichChild.getValue()
FreeCAD.Console.PrintWarning("getDetailPath: mode {} is active\n".format(mode))
if mode >= 0:
mode = vobj.SwitchNode.getChild(mode)
path.append(mode)
sub = Part.splitSubname(subname)[-1]
print(sub)
if sub == 'Atom1':
path.append(self.sel1)
elif sub == 'Atom2':
path.append(self.sel2)
elif sub == 'Line':
path.append(self.sel3)
else:
path.append(mode.getChild(0))
return True
def getElementPicked(self, pp):
path = pp.getPath()
if path.findNode(self.sel1) >= 0:
return 'Atom1'
if path.findNode(self.sel2) >= 0:
return 'Atom2'
if path.findNode(self.sel3) >= 0:
return 'Line'
raise NotImplementedError
def updateData(self, fp, prop):
"If a property of the handled feature has changed we have the chance to handle this here"
# fp is the handled feature, prop is the name of the property that has changed
if not self.constructed:
return
if prop == "p1":
p = fp.getPropertyByName("p1")
self.coords.point.set1Value(0, p)
elif prop == "p2":
p = fp.getPropertyByName("p2")
self.coords.point.set1Value(1, p)
def getDisplayModes(self, obj):
return ['Wireframe', 'Shaded']
def getDefaultDisplayMode(self):
return 'Shaded'
def setDisplayMode(self, mode):
return mode
def __getstate__(self):
return None
def __setstate__(self,state):
return None
def makeMolecule():
FreeCAD.newDocument()
a=FreeCAD.ActiveDocument.addObject("App::FeaturePython","Molecule")
Molecule(a)
b=ViewProviderMolecule(a.ViewObject)
a.touch()
FreeCAD.ActiveDocument.recompute()
return a,b
a,b = makeMolecule()
10
.
Grid spacing 1000mm
to have a one meter-based grid, which is convenient for the size of our building.
Grid size 100 lines
.
On the snapping toolbar make sure the ![]() |
The parameters in this menu are similar to those described above. Base Placement: allows you to move or rotate the helix Angle: |
true
Flat Lines
and Wireframe
.
FreeCAD.
a window pops up, allowing to quickly autocomplete the rest of your line.
Even better, each entry in the autocomplete list has a tooltip explaining what it does.
This makes it easier to explore the available functionality.
Before choosing newDocument
, have a look at the other options.
Object
, its "geometry" component, and a ViewObject
, its "visual" component.
When you work in command-line mode, the geometry part is present, but the visual part is disabled.
To illustrate the concept let's look at our cube object.
The geometric properties of the cube, such as its dimensions, position, etc.
are stored in the Object
.
While its visual properties, such as its color, line thickness, etc.
are stored in the ViewObject
.
This corresponds to the Data and View tabs in the Property editor.
The view object of an object is accessed like this:
vo = box.ViewObject
Now you can also change the properties on the View tab:
vo.Transparency = 80
vo.hide()
vo.show()
When you start FreeCAD, the Python console already loads two base modules: FreeCAD
and FreeCADGui
(which can also be accessed by their shortcuts App
and Gui
).
They contain all kinds of generic functionality to work with documents and their objects.
To illustrate our concept, see that both FreeCAD
and FreeCADGui
contain an ActiveDocument
attribute, which is the currently opened document.
FreeCAD.ActiveDocument
and FreeCADGui.ActiveDocument
are not the same object however.
They are the two components of a FreeCAD document, and they contain different attributes and methods.
For example, FreeCADGui.ActiveDocument
contains ActiveView
, which is the currently opened 3D view.
createSphere()
method to create a sphere, but you can also create custom meshes from scratch by defining their vertices and faces.
Read more about mesh scripting...
Faces
, Edges
, Vertexes
, Solids
and Shells
, and a wide range of geometry operations such as cut
(subtraction), common
(intersection) or fuse
(union).
The Topological data scripting page explains all that in detail.
Read more about part scripting...
.py
extension in the internal Python editor, the most simple trick is create in your favorite text editor and then open it with the usual command File → Open.
To make the things in a polite way, the file has to be written with some order, FreeCAD Python editor have a good "Syntax HIghlighting" that lacks in many simple editors like Windows Notepad or some basic Linux editors, so it is sufficient to write these few lines:
"""script.py
Primo script per FreeCAD
"""
.py
extension and load the resulting file in FreeCAD, with the said File - Open command.
import FreeCAD
This line import FreeCAD in the FreeCAD Python interpreter, it may seem a redundant thing, but it isn't.
from FreeCAD import Base, Vector
Base and Vector are widely used in FreeCAD scripting, import them in this manner will save you to invoke them with FreeCAD.Vector
or FreeCAD.Base
instead of Base
or Vector
, this will save many keystrokes and make codelines much smaller.
cubo(
method and before the line # objects definition
.
def base_cyl(nome, ang, rad, alt ):
obj = DOC.addObject("Part::Cylinder", nome)
obj.Angle = ang
obj.Radius = rad
obj.Height = alt
DOC.recompute()
return obj
Even here nothing too exciting.
But please note some peculiarities:
The absence of the usual reference to the App.
, present in many Documentation code snippets, is deliberate, this code could be used even invoking FreeCAD as a module in an external Python interpreter, the thing is not easily doable with an AppImage, but with some care it could be done.
Plus in the standard Python motto that "better explicit than implicit" App.
is explaining in a very "poor" way where the things are from.
Note the use of the "constant" name assigned to the active Document in DOC
= FreeCAD.activeDocument()
; activeDocument is not a "constant" in a strict sense, but in a "semantical" way is our "active Document", that for our use is a proper "constant" so the Python convention to use the "ALL CAPS" name for "constants", not to mention that DOC
is much shorten than FreeCAD.activeDocument()
.
Every method returns a geometry, this will be clear in the continuation of the page.
Geometry didn't have the Placement
property, when using the simple geometries to make more complex geometry, managing Placement
is a awkward thing.
Now what to do with this geometries?
Let's introduce boolean operations.
As a starter example put these lines after base_cyl(...
, this create a method for a Fusion also know as Union operation:
def fuse_obj(nome, obj_0, obj_1):
obj = DOC.addObject("Part::Fuse", nome)
obj.Base = obj_0
obj.Tool = obj_1
obj.Refine = True
DOC.recompute()
return obj
Nothing exceptional also here, note however the uniformity in method coding; This approach is more linear that those seen around other tutorial on scripting, this "linearity" help greatly in readability and also with cut-copy-paste operations.
Let's use the geometries, delete lines below the code section starting with # objects definition
, and insert the following lines:
# objects definition
obj = cubo("cubo_di_prova", 5, 5, 5)
obj1 = base_cyl('primo cilindro', 360,2,10)
fuse_obj("Fusione", obj, obj1)
setview()
Launch the script with the green arrow and we will see in the 3D view something like:
Placement
property.
FreeCAD offer a wide choice of ways to set this property, one is more tailored to another depending the knowledge and the background of the user, but the more plain writing is explained in the cited Tutorial, it use a peculiar definition of the Rotation
portion of Placement
, quite easy to learn.
FreeCAD.Placement(Vector(0,0,0), FreeCAD.Rotation(10,20,30), Vector(0,0,0))
But over other consideration, one thing is crucial, geometry reference point, in other word the point from which the object is modeled by FreeCAD, as described in this table, copied from Placement:
Object | Reference Point |
---|---|
Part.Box | left (minx), front (miny), bottom (minz) vertex |
Part.Sphere | center of the sphere (ie centre of bounding box) |
Part.Cylinder | center of the bottom face |
Part.Cone | center of bottom face (or apex if bottom radius is 0) |
Part.Torus | center of the torus |
Features derived from Sketches | the Feature inherits the Position of the underlying Sketch. Sketches always start with Position = (0,0,0). This position corresponds to the origin in the sketch. |
base_cyl
method and insert the portion of code below:
def sfera(nome, rad):
obj = DOC.addObject("Part::Sphere", nome)
obj.Radius = rad
DOC.recompute()
return obj
def mfuse_obj(nome, objs):
obj = DOC.addObject("Part::MultiFuse", nome)
obj.Shapes = objs
obj.Refine = True
DOC.recompute()
return obj
def aeroplano():
lung_fus = 30
diam_fus = 5
ap_alare = lung_fus * 1.75
larg_ali = 7.5
spess_ali = 1.5
alt_imp = diam_fus * 3.0
pos_ali = (lung_fus*0.70)
off_ali = (pos_ali - (larg_ali * 0.5))
obj1 = base_cyl('primo cilindro', 360, diam_fus, lung_fus)
obj2 = cubo('ali', ap_alare, spess_ali, larg_ali, True, off_ali)
obj3 = sfera("naso", diam_fus)
obj3.Placement = FreeCAD.Placement(Vector(0,0,lung_fus), FreeCAD.Rotation(0,0,0), Vector(0,0,0))
obj4 = cubo('impennaggio', spess_ali, alt_imp, larg_ali, False, 0)
obj4.Placement = FreeCAD.Placement(Vector(0,alt_imp * -1,0), FreeCAD.Rotation(0,0,0), Vector(0,0,0))
objs = (obj1, obj2, obj3, obj4)
obj = mfuse_obj("Forma esempio", objs)
obj.Placement = FreeCAD.Placement(Vector(0,0,0), FreeCAD.Rotation(0,0,-90), Vector(0,0,pos_ali))
DOC.recompute()
return obj
# objects definition
aeroplano()
setview()
Let's explain something in the code:
We have used a method to define a sphere, using the most easy definition, using only the radius.
We have introduced a second writing for the Union or Fusion, using multiple objects, not more distant from the usual Part::Fuse it uses Part:Multifuse.
We only use one property Shapes
.
We have passed a tuple as arguments, but it accepts also a list.
We have defined a complex object aeroplano (italian word for aeroplane), but we have done it in a "parametric" way, defining some parameters and deriving other parameters, through some calculation, based on the main parameters.
We have used some Placement Placement
poperties around in the method and before returning the final geometries we have used a Rotation
property with the Yaw-Pitch-Roll writing.
Note the last Vector(0,0, pos_ali)
, that define a center of rotation of the whole geometry.
![]() |
![]() |
![]() |
Vector(0,0,0)
is the Translation vector, not used here, but if you substitute aeroplano()
with these lines:
obj_f = aeroplano()
print(obj_F.Placement)
You will see in the Report window this text:
Placement [Pos=(0,-21,21), Yaw-Pitch-Roll=(0,0,-90)]
What has happened?
FreeCAD has translated the Vector(0,0,0), FreeCAD.Rotation(0,0,-90), Vector(0,0,pos_ali)
in other word our Placement
definition that specifies three components, Translation', Rotation and center of rotation in the "internal" values of only two components, Translation and Rotation.
you can easily visualize the value of pos_ali
using a print statement in the aeroplano(...
method and see that it is:
pos ali = 21.0
in other word the rotation center of the geometry is at Vector(0,0,21)
, but this rotation center is not shown in the GUI, it could be entered as a Placement
value, it could not be easily retrieved.
This is the meaning of the word "awkward" that I've used to define Placement
property.
make...()
methods from the Part module:
b = Part.makeBox(100, 100, 100)
Part.show(b)
Some available make...()
methods:
makeBox(l, w, h, [p, d])
Makes a box located in p and pointing into the direction d with the dimensions (l,w,h).
makeCircle(radius)
Makes a circle with a given radius.
makeCone(radius1, radius2, height)
Makes a cone with the given radii and height.
makeCylinder(radius, height)
Makes a cylinder with a given radius and height.
makeLine((x1, y1, z1), (x2, y2, z2))
Makes a line from two points.
makePlane(length, width)
Makes a plane with length and width.
makePolygon(list)
Makes a polygon from a list of points.
makeSphere(radius)
Makes a sphere with a given radius.
makeTorus(radius1, radius2)
Makes a torus with the given radii.
See the Part API page for a complete list of available methods of the Part module.
Part.show(wire3)
will display the 4 edges that compose our wire.
Other useful information can be easily retrieved:
wire3.Length
> 40.0
wire3.CenterOfMass
> Vector (5, 5, 0)
wire3.isClosed()
> True
wire2.isClosed()
> False
makeCircle()
only accepts Base.Vector()
for the position
and normal parameters, not tuples.
You can also create part of the circle by giving a start and an end angle:
from math import pi
arc1 = Part.makeCircle(10, Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), 0, 180)
arc2 = Part.makeCircle(10, Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), 180, 360)
Angles should be provided in degrees.
If you have radians simply convert them using the formula:
degrees = radians * 180/pi
or by using Python's math
module:
import math
degrees = math.degrees(radians)
makeArc()
function, but we have the Part.Arc()
function to create an arc through three points.
It creates an arc object joining the start point to the end point through the middle point.
The arc object's toShape()
function must be called to get an edge object, the same as when using Part.LineSegment
instead of Part.makeLine
.
arc = Part.Arc(Base.Vector(0, 0, 0), Base.Vector(0, 5, 0), Base.Vector(5, 5, 0))
arc
> <Arc object>
arc_edge = arc.toShape()
Part.show(arc_edge)
Arc()
only accepts Base.Vector()
for points and not tuples.
You can also obtain an arc by using a portion of a circle:
from math import pi
circle = Part.Circle(Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), 10)
arc = Part.Arc(circle,0,pi)
Arcs are valid edges like lines, so they can be used in wires also.
makePolygon()
function takes a list of points and creates a wire through those points:
lshape_wire = Part.makePolygon([Base.Vector(0, 5, 0), Base.Vector(0, 0, 0), Base.Vector(5, 0, 0)])
Part.BezierCurve()
from a series of FreeCAD.Vector()
points.
Note: when "getting" and "setting" a single pole or weight, indices start at 1, not 0.
def makeBCurveEdge(Points):
geomCurve = Part.BezierCurve()
geomCurve.setPoles(Points)
edge = Part.Edge(geomCurve)
return(edge)
makePlane(length, width, [start_pnt, dir_normal])
.
By default start_pnt = Vector(0, 0, 0) and dir_normal = Vector(0, 0, 1).
Using dir_normal = Vector(0, 0, 1) will create the plane facing in the positive Z axis direction, while dir_normal = Vector(1, 0, 0) will create the plane facing in the positive X axis direction:
plane = Part.makePlane(2, 2)
plane
> <Face object at 028AF990>
plane = Part.makePlane(2, 2, Base.Vector(3, 0, 0), Base.Vector(0, 1, 0))
plane.BoundBox
> BoundBox (3, 0, 0, 5, 0, 2)
BoundBox
is a cuboid enclosing the plane with a diagonal starting at (3, 0, 0) and ending at (5, 0, 2).
Here the BoundBox
thickness along the Y axis is zero, since our shape is totally flat.
Note: makePlane()
only accepts Base.Vector()
for start_pnt and dir_normal and not tuples.
Arc
, Ellipse
creates an ellipse object not an edge, so we need to convert it into an edge using toShape()
for display.
Note: Ellipse()
only accepts Base.Vector()
for points and not tuples.
eli = Part.Ellipse(Base.Vector(0, 0, 0), 10, 5)
Part.show(eli.toShape())
For the above Ellipse constructor we have passed center, MajorRadius and MinorRadius.
makeTorus(radius1, radius2, [pnt, dir, angle1, angle2, angle])
.
By default pnt = Vector(0, 0, 0), dir = Vector(0, 0, 1), angle1 = 0, angle2 = 360 and angle = 360.
Consider a torus as small circle sweeping along a big circle.
Radius1 is the radius of the big circle, radius2 is the radius of the small circle, pnt is the center of the torus and dir is the normal direction.
angle1 and angle2 are angles in degrees for the small circle; the last angle parameter is to make a section of the torus:
torus = Part.makeTorus(10, 2)
The above code will create a torus with diameter 20 (radius 10) and thickness 4 (small circle radius 2)
tor=Part.makeTorus(10, 5, Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), 0, 180)
The above code will create a slice of the torus.
tor=Part.makeTorus(10, 5, Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), 0, 360, 180)
The above code will create a semi torus; only the last parameter is changed.
i.e the remaining angles are defaults.
Giving the angle 180 will create the torus from 0 to 180, that is, a half torus.
makeBox(length, width, height, [pnt, dir])
.
By default pnt = Vector(0, 0, 0) and dir = Vector(0, 0, 1).
box = Part.makeBox(10, 10, 10)
len(box.Vertexes)
> 8
makeSphere(radius, [pnt, dir, angle1, angle2, angle3])
.
By default pnt = Vector(0, 0, 0), dir = Vector(0, 0, 1), angle1 = -90, angle2 = 90 and angle3 = 360.
Angle1 and angle2 are the vertical minimum and maximum of the sphere, angle3 is the sphere diameter.
sphere = Part.makeSphere(10)
hemisphere = Part.makeSphere(10, Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), -90, 90, 180)
makeCylinder(radius, height, [pnt, dir, angle])
.
By default pnt = Vector(0, 0, 0), dir = Vector(0, 0, 1) and angle = 360.
cylinder = Part.makeCylinder(5, 20)
partCylinder = Part.makeCylinder(5, 20, Base.Vector(20, 0, 0), Base.Vector(0, 0, 1), 180)
makeCone(radius1, radius2, height, [pnt, dir, angle])
.
By default pnt = Vector(0, 0, 0), dir = Vector(0, 0, 1) and angle = 360.
cone = Part.makeCone(10, 0, 20)
semicone = Part.makeCone(10, 0, 20, Base.Vector(20, 0, 0), Base.Vector(0, 0, 1), 180)
transformShape()
and transformGeometry()
.
The difference
is that with the first one, you are sure that no deformations will occur (see Scaling a shape below).
We can apply our transformation like this:
myShape.transformShape(myMat)
or
myShape.transformGeometry(myMat)
transformShape()
, we must use transformGeometry()
:
myMat = Base.Matrix()
myMat.scale(2, 1, 1)
myShape=myShape.transformGeometry(myMat)
makeBox()
command created a solid shape.
This solid, like all Part solids, contains faces.
Faces always contain wires, which are lists of edges that border the face.
Each face has at least one closed wire (it can have more if the face has a hole).
In the wire, we can look at each edge separately, and inside each edge, we can see the vertices.
Straight edges have only two vertices, obviously.
Part
module, but also the FreeCAD.Base
module, which contains basic FreeCAD structures like vectors and matrices.
def makeBottleTut(myWidth = 50.0, myHeight = 70.0, myThickness = 30.0):
aPnt1=Base.Vector(-myWidth / 2., 0, 0)
aPnt2=Base.Vector(-myWidth / 2., -myThickness / 4., 0)
aPnt3=Base.Vector(0, -myThickness / 2., 0)
aPnt4=Base.Vector(myWidth / 2., -myThickness / 4., 0)
aPnt5=Base.Vector(myWidth / 2., 0, 0)
Here we define our makeBottleTut
function.
This function can be called without arguments, like we did above, in which case default values for width, height, and thickness will be used.
Then, we define a couple of points that will be used for building our base profile.
...
aArcOfCircle = Part.Arc(aPnt2, aPnt3, aPnt4)
aSegment1=Part.LineSegment(aPnt1, aPnt2)
aSegment2=Part.LineSegment(aPnt4, aPnt5)
Here we define the geometry: an arc, made of three points, and two line segments, made of two points.
...
aEdge1=aSegment1.toShape()
aEdge2=aArcOfCircle.toShape()
aEdge3=aSegment2.toShape()
aWire=Part.Wire([aEdge1, aEdge2, aEdge3])
Remember the difference between geometry and shapes? Here we build shapes out of our construction geometry.
Three edges (edges can be straight or curved), then a wire made of those three edges.
...
aTrsf=Base.Matrix()
aTrsf.rotateZ(math.pi) # rotate around the z-axis
aMirroredWire=aWire.copy()
aMirroredWire.transformShape(aTrsf)
myWireProfile=Part.Wire([aWire, aMirroredWire])
So far we have built only a half profile.
Instead of building the whole profile the same way, we can just mirror what we did and glue both halves together.
We first create a matrix.
A matrix is a very common way to apply transformations to objects in the 3D world, since it can contain in one structure all basic transformations that 3D objects can undergo (move, rotate and scale).
After we create the matrix we mirror it, then we create a copy of our wire and apply the transformation matrix to it.
We now have two wires, and we can make a third wire out of them, since wires are actually lists of edges.
...
myFaceProfile=Part.Face(myWireProfile)
aPrismVec=Base.Vector(0, 0, myHeight)
myBody=myFaceProfile.extrude(aPrismVec)
myBody=myBody.makeFillet(myThickness / 12.0, myBody.Edges)
Now that we have a closed wire, it can be turned into a face.
Once we have a face, we can extrude it.
In doing so, we make a solid.
Then we apply a nice little fillet to our object because we care about good design, don't we?
...
neckLocation=Base.Vector(0, 0, myHeight)
neckNormal=Base.Vector(0, 0, 1)
myNeckRadius = myThickness / 4.
myNeckHeight = myHeight / 10.
myNeck = Part.makeCylinder(myNeckRadius, myNeckHeight, neckLocation, neckNormal)
At this point, the body of our bottle is made, but we still need to create a neck.
So we make a new solid, with a cylinder.
...
myBody = myBody.fuse(myNeck)
The fuse operation is very powerful.
It will take care of gluing what needs to be glued and remove parts that need to be removed.
...
return myBody
Then, we return our Part solid as the result of our function.
el = makeBottleTut()
Part.show(el)
Finally, we call the function to actually create the part, then make it visible.
exportBrep()
, exportIges()
, exportStep()
and exportStl()
methods available for all shape objects.
So, doing:
import Part
s = Part.makeBox(10, 10, 10)
s.exportStep("test.stp")
will save our box into a STEP file.
To load a BREP, IGES or STEP file:
import Part
s = Part.Shape()
s.read("test.stp")
To convert a STEP file to an IGS file:
import Part
s = Part.Shape()
s.read("file.stp") # incoming file igs, stp, stl, brep
s.exportIges("file.igs") # outbound file igs